现在有个需求是,数据库存了用户解锁的头像数组,每次都要json序列化和反序列化.之前是给Avatar结构体写了两个方法,发现太麻烦了
Scan和Value分别对应读取和存储。同理,可以扩展其他类型,比如时间
方法1-适合复杂的数据类型
package domain
import (
"database/sql/driver"
"encoding/json"
"errors"
)
// AvatarListJSON 自定义int切片类型,用于数据库JSON字段的自动序列化和反序列化
type AvatarListJSON []int
// Scan 实现sql.Scanner接口,从数据库读取JSON数据并转换为AvatarListJSON
func (al *AvatarListJSON) Scan(value interface{}) error {
bytes, ok := value.([]byte)
if !ok {
return errors.New("invalid type for AvatarListJSON")
}
if len(bytes) == 0 {
*al = []int{}
return nil
}
var temp []int
if err := json.Unmarshal(bytes, &temp); err != nil {
return err
}
*al = AvatarListJSON(temp)
return nil
}
// Value 实现driver.Valuer接口,将AvatarListJSON转换为JSON字符串存储到数据库
func (al AvatarListJSON) Value() (driver.Value, error) {
if len(al) == 0 {
return "[]", nil
}
bytes, err := json.Marshal(al)
if err != nil {
return nil, err
}
return string(bytes), nil
}
// Avatar 头像结构体
type Avatar struct {
ID int64 `gorm:"primaryKey" json:"id"`
UID int `gorm:"index" json:"uid"` // 所属用户
Avatar AvatarListJSON `gorm:"column:avatar" json:"avatar"` // 头像id列表,JSON格式存储
}
func (*Avatar) TableName() string {
return "avatar"
}
方法2-推荐,支持json格式,serializer会自动序列化
type Avatar struct {
ID int64 `gorm:"primaryKey" json:"id"`
UID int `gorm:"index" json:"uid"` // 所属用户
Avatar []int `gorm:"column:avatar;serializer:json;default:'[]'" json:"avatar"` // 头像id列表,JSON格式存储
}