If your gorm.io/driver/postgres version is v1.4.6 (pgx version is github.com/jackc/pgx/v5), gorm model field is mapped to proto enum, will be failed, You need an explicit gen Scan & Value method.
https://github.com/go-gorm/postgres/blob/v1.4.5/go.mod -> github.com/jackc/pgx/v4 v4.17.2
https://github.com/go-gorm/postgres/blob/v1.4.6/go.mod -> github.com/jackc/pgx/v5 v5.2.0
protoc-gen-gorm-serializer
go install github.com/yangyang5214/protoc-gen-gorm-serializer@latest
Add --go_out as a parameter to protoc, for example:
- task.proto
syntax = "proto3";
enum TaskStatus {
Unknown = 0;
Running = 1;
Exiting = 2;
Pending = 3;
}
option go_package = "github.com/yangyang5214/protoc-gen-gorm-serializer/example";
- run protoc cmd
protoc --proto_path=. --go_out=paths=source_relative:. --gorm-serializer_out=paths=source_relative:. task.proto
- gen task_gorm_serializer.pb.go file
// Code generated by protoc-gen-gorm_serializer. DO NOT EDIT.
// versions:
// - protoc v3.21.12
// source: task.proto
package example
import "database/sql/driver"
func (x *TaskStatus) Scan(v any) (err error) {
*x = TaskStatus(v.(int64))
return nil
}
func (x TaskStatus) Value() (v driver.Value, err error) {
return int32(x), nil
}
- use gorm field
type Task struct {
gorm.Model
Name string
Status example.TaskStatus `gorm:"type:int"`
}
func (Task) TableName() string {
return "task"
}
func main() {
db, err := gorm.Open(sqlite.Open("/tmp/test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
err = db.AutoMigrate(&Task{})
if err != nil {
panic(err)
}
t := &Task{
Name: "task_name_test",
Status: example.TaskStatus_Exiting,
}
// Create
tx := db.Create(t)
if tx.Error != nil {
panic(tx.Error)
}
// Read
var task Task
db.Where(Task{Name: "task_name_test"})
db.First(&task)
fmt.Println(fmt.Sprintf("task status is: %s", task.Status))
}
https://github.com/yangyang5214/protoc-gen-gorm-serializer-example
https://github.com/go-kratos/kratos/tree/main/cmd/protoc-gen-go-http