如何在GORM中为PostgreSQL表定义enum枚举类型?
PostgreSQL + GORM 配置枚举类型的实现方案
下面提供两种常用的实现思路,可根据业务场景选择:
方案1:使用PostgreSQL原生ENUM类型(数据库层面强约束)
- 第一步:先在PostgreSQL数据库中创建枚举类型,执行SQL:
CREATE TYPE car_type AS ENUM ('SEDAN', 'HATCHBACK', 'MINIVAN');
- 第二步:修改GORM结构体的tag,指定字段匹配刚刚创建的枚举类型即可,调整后结构体如下:
type TestTable struct { ID int `gorm:"column:id;primaryKey;autoIncrement"` CarType string `gorm:"column:car_type;type:car_type"` }
如果需要配合GORM自动迁移逻辑使用,可以在迁移执行前先运行创建枚举类型的SQL,避免迁移时因为类型不存在报错。
方案2:Go代码层面做枚举约束(无需修改数据库额外类型)
如果不想在数据库中新增枚举类型,也可以通过自定义Go类型 + 实现driver.Valuer、sql.Scanner接口的方式实现枚举约束:
- 第一步:定义自定义枚举类型和合法取值
type CarType string const ( CarTypeSedan CarType = "SEDAN" CarTypeHatchback CarType = "HATCHBACK" CarTypeMinivan CarType = "MINIVAN" )
- 第二步:实现Valuer接口,写入数据库前校验取值合法性
func (ct CarType) Value() (driver.Value, error) { validTypes := map[CarType]struct{}{ CarTypeSedan: {}, CarTypeHatchback: {}, CarTypeMinivan: {}, } if _, ok := validTypes[ct]; !ok { return nil, fmt.Errorf("invalid car type: %s", ct) } return string(ct), nil }
- 第三步:实现Scanner接口,从数据库读取数据时自动转换为自定义类型
func (ct *CarType) Scan(value interface{}) error { strVal, ok := value.(string) if !ok { return fmt.Errorf("failed to scan car type, value is not string type") } *ct = CarType(strVal) return nil }
- 第四步:修改结构体字段为自定义的CarType类型
type TestTable struct { ID int `gorm:"column:id;primaryKey;autoIncrement"` CarType CarType `gorm:"column:car_type"` }
注意:该方案仅在Go代码层面做约束,数据库层面存储的仍然是普通字符串,如果有其他服务直接操作数据库可能写入非法值,对数据一致性要求高的场景推荐使用方案1。
内容的提问来源于stack exchange,提问作者deepika azad
相关产品推荐
相关产品推荐

