我正在写PostgreSQL表模式
type TestTable struct {
ID int `gorm:"column:id;primaryKey;autoIncrement"`
CarType string `gorm:"column:car_type"`
}
那么我如何添加像"轿车"、"掀背"、"minivan"这样的汽车类型呢?enum 数据类型
假设您正在使用GORM与PostgreSQL。首先在数据库中创建一个类型。
CREATE TYPE car_type AS ENUM (
'SEDAN',
'HATCHBACK',
'MINIVAN');
那么您将需要定义以下模型:
import "database/sql/driver"
type carType string
const (
SEDAN carType = "SEDAN"
HATCHBACK carType = "HATCHBACK"
MINIVAN carType = "MINIVAN"
)
func (ct *carType) Scan(value interface{}) error {
*ct = carType(value.([]byte))
return nil
}
func (ct carType) Value() (driver.Value, error) {
return string(ct), nil
}
type MyTable struct {
gorm.Model
CarType carType `gorm:"type:car_type"`
}
func (MyTable) TableName() string {
return "my_table"
}
注意MySQL用户,你可以添加结构标记gorm:
或sql:
,这样你就不必运行原始查询在数据库中创建enum。
CarType carType `gorm:"type:enum('SEDAN', 'HATCHBACK', 'MINIVAN')";"column:car_type"`
或
CarType carType `sql:"type:ENUM('SEDAN', 'HATCHBACK', 'MINIVAN')" gorm:"column:car_type"`
编辑:有人指出这只适用于MySQL。我想把我的答案拿下来,但是使用MySQL的人可能会发现它很有帮助。
这里有一个不需要事先创建SQL类型的答案。这个解决方案的来源是这个github问题
对于您的字段标签,使用如下:
type TestTable struct {
ID int `gorm:"column:id;primaryKey;autoIncrement"`
CarType carType `sql:"type:ENUM('SEDAN', 'HATCHBACK', 'MINIVAN')" gorm:"column:car_type"`
}
您还需要添加附加到carType类型的Scan和Value方法。
type carType string
const (
SEDAN carType = "SEDAN"
HATCHBACK carType = "HATCHBACK"
MINIVAN carType = "MINIVAN"
)
func (self *carType) Scan(value interface{}) error {
*self = carType(value.([]byte))
return nil
}
func (self carType) Value() (driver.Value, error) {
return string(self), nil
}
附带说明-如果您决定采用稍微不同的方法:您可以将枚举定义为int,并利用iota
。然后你可以使用代码生成器创建sqlScaner/Valuer
,也json/文本表示。例如:https://github.com/dmarkham/enumer
为了扩展Nick的回答,我为自动化添加了以下内容:
假设你有DBClient
结构体,你可以创建一个方法来创建这个汽车类型:
func (psqlClient *DBClient) CreateCarTypeEnum() error {
result := psqlClient.db.Exec("SELECT 1 FROM pg_type WHERE typname = 'car_type';")
switch {
case result.RowsAffected == 0:
if err := psqlClient.db.Exec("CREATE TYPE car_type AS ENUM ('SEDAN', 'HATCHBACK', 'MINIVAN');").Error; err != nil {
log.Error().Err(err).Msg("Error creating car_type ENUM")
return err
}
return nil
case result.Error != nil:
return result.Error
default:
return nil
}
}
就像你在sql中写的那样,你可以使用type和添加任何你想要的数据类型。
type MyTable struct {
CarType string `gorm:"column:car_type;type:enum('SEDAN','HATCHBACK','MINIVAN')" json:"car_type"`
}
一个更新,它将不与sql:"car_type"
工作,而是使用gorm:"car_type"
。当您在数据库中手动创建了自定义enum类型后,也是如此。
https://gorm.io/docs/data_types.html =>impl Scan &值方法。
如果enum是由协议生成的,可以使用这个插件
https://github.com/yangyang5214/protoc-gen-gorm-serializer。
# task.proto
syntax = "proto3";
enum TaskStatus {
Unknown = 0;
Running = 1;
Exiting = 2;
Pending = 3;
}
# gen gorm-serializer.pb.go
protoc --proto_path=. --go_out=paths=source_relative:. --gorm-serializer_out=paths=source_relative:. task.proto
# use
type Task struct {
gorm.Model
Name string
Status example.TaskStatus `gorm:"type:int"`
}