使用 GORM 将接口设置为具有许多实现的属性
Setting Interface as an attribute having many implementations using GORM
我有一个 Postgres 数据库,它存储 JSON 作为它的字段之一。 table 的结构是:
type Table struct {
ID int
VehicleType string
Vehicle Vehicle `gorm:"type:jsonb"`
// ......
}
现在,Vehicle 是一个接口
type Vehicle interface {
GetEngineModel() string
}
它有很多实现,我将分享其中一个 - Car
type Car struct {
CarEngineModel string //the attributes will be different for different
//implementation
}
func (car Car) GetEngineModel() string {
return car.CarEngineModel
}
为了解析特定结构中的属性,即 Car、Bike、..,我可以像这样实现所有实现的 Scan 和 Value 接口:-
func (car *Car) Scan(value interface{}) error {
//Want to use this implementation of Scan based on VehicleType
//attribute of struct table
b, ok := value.([]byte)
if !ok {
return errors.New("type assertion to []byte failed")
}
*car = json.Unmarshal(b, &car)
}
有没有办法根据其他 table 列或使用 GORM 的替代方法来判断要使用哪种 Scan 实现?我只想要一个 table(遗传 json 类型)所以不想使用不同的 tables 用于使用多态关联的不同实现。
您可以添加一个单独的字段来保存原始 JSON 数据,然后对 marshal/unmarshal 该数据实施 gorm
特定挂钩。
type Table struct {
ID int
VehicleType string
Vehicle Vehicle `gorm:"-"`
// ...
VehicleRaw []byte `gorm:"column:vehicle"`
}
func (t *Table) BeforeSave(tx *gorm.DB) (err error) {
raw, err := json.Marshal(t.Vehicle)
if err != nil {
return err
}
t.VehicleRaw = raw
return nil
}
func (t *Table) AfterFind(tx *gorm.DB) (err error) {
switch t.VehicleType {
case "CAR":
t.Vehicle = &Car{}
case "BIKE":
t.Vehicle = &Bike{}
}
return json.Unmarshal(t.VehicleRaw, t.Vehicle)
}
我有一个 Postgres 数据库,它存储 JSON 作为它的字段之一。 table 的结构是:
type Table struct {
ID int
VehicleType string
Vehicle Vehicle `gorm:"type:jsonb"`
// ......
}
现在,Vehicle 是一个接口
type Vehicle interface {
GetEngineModel() string
}
它有很多实现,我将分享其中一个 - Car
type Car struct {
CarEngineModel string //the attributes will be different for different
//implementation
}
func (car Car) GetEngineModel() string {
return car.CarEngineModel
}
为了解析特定结构中的属性,即 Car、Bike、..,我可以像这样实现所有实现的 Scan 和 Value 接口:-
func (car *Car) Scan(value interface{}) error {
//Want to use this implementation of Scan based on VehicleType
//attribute of struct table
b, ok := value.([]byte)
if !ok {
return errors.New("type assertion to []byte failed")
}
*car = json.Unmarshal(b, &car)
}
有没有办法根据其他 table 列或使用 GORM 的替代方法来判断要使用哪种 Scan 实现?我只想要一个 table(遗传 json 类型)所以不想使用不同的 tables 用于使用多态关联的不同实现。
您可以添加一个单独的字段来保存原始 JSON 数据,然后对 marshal/unmarshal 该数据实施 gorm
特定挂钩。
type Table struct {
ID int
VehicleType string
Vehicle Vehicle `gorm:"-"`
// ...
VehicleRaw []byte `gorm:"column:vehicle"`
}
func (t *Table) BeforeSave(tx *gorm.DB) (err error) {
raw, err := json.Marshal(t.Vehicle)
if err != nil {
return err
}
t.VehicleRaw = raw
return nil
}
func (t *Table) AfterFind(tx *gorm.DB) (err error) {
switch t.VehicleType {
case "CAR":
t.Vehicle = &Car{}
case "BIKE":
t.Vehicle = &Bike{}
}
return json.Unmarshal(t.VehicleRaw, t.Vehicle)
}