7.gorm新-自定义数据类型

很多情况下,我们有存json的需求

那么就需要使用到gorm中的自定义数据类型了

自定义的数据类型必须实现 Scanner 和 Valuer 接口

简单说就是,在入库的时候转换一下,变成普通字符串进行存储,查询的时候,映射为结构体

JSON自定义数据类型

json数据用的比较多

type Info struct {
  Like []string `json:"like"`
  Addr string   `json:"addr"`
  Age  int      `json:"age"`
}

// Scan 实现 sql.Scanner 接口,Scan 将 value 扫描至 Jsonb
func (j *Info) Scan(value interface{}) error {
  bytes, ok := value.([]byte)
  if !ok {
    return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value))
  }

  result := Info{}
  err := json.Unmarshal(bytes, &result)
  *j = result
  return err
}

// Value 实现 driver.Valuer 接口,Value 返回 json value
func (j Info) Value() (driver.Value, error) {
  return json.Marshal(j)
}

注意:这里千万不要自作聪明,去改指针方法或者接受者方法,Scan是指针方法,Value是接受者方法

插入数据

type User struct {
  ID   int64
  Name string `gorm:"size:32"`
  Info Info   `gorm:"type:longtext" json:"info"`
}
DB.Create(&User{
  Name: "枫枫",
  Info: Info{
    Age:  21,
    Addr: "湖南长沙",
    Like: []string{"唱", "跳", "rap"},
  },
})

查询数据

var user User
DB.Take(&user, 1)
fmt.Println(user.Name, user.Info.Like)

序列化

如果只是存储json数据,完全可以使用gorm的序列化,自带json

type User struct {
  ID   int64
  Name string `gorm:"size:32"`
  Info Info   `gorm:"type:longtext;serializer:json" json:"info"`
}

当然也可以自定义序列化器,参考如下:

序列化 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.

枚举类型

有些情况下,在数据库里面需要存储一些标识状态的内容

比如描述日志的等级,通常有固定的那么几个值,例如info、warning、error

如果直接存储字符串,很明显是浪费空间

所以可以使用自定义类型

type Status int8

const (
  Running Status = 1
  Warning Status = 2
)

func (s Status) MarshalJSON() (data []byte, err error) {
  var str string
  switch s {
  case Running:
    str = "运行中"
  case Warning:
    str = "警告"
  }
  return json.Marshal(str)
}

type User struct {
  ID     int64
  Name   string `gorm:"size:32"`
  Status Status `json:"status"`
}


因为返回前端的时候,肯定会走json序列化,所以返回给前端的时候就是对应的中文

不过也可以再优化一下,只返回中文又太少了,还需要把它本身的数字也给返回出来,怎么做呢

func (s Status) MarshalJSON() (data []byte, err error) {
  var str string
  switch s {
  case Running:
    str = "运行中"
  case Warning:
    str = "警告"
  }
  return json.Marshal(map[string]any{
    "status":      int8(s),
    "statusTitle": str,
  })
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值