gorm 学习笔记 五:自定义数据类型和枚举

一:Json类型

Info保存到数据库时,通过Value()转化为json,读取出来的时候 json字符串自动转成结构体Info

Go 复制代码
type Info struct {
  Status string `json:"status"`
  Addr   string `json:"addr"`
  Age    int    `json:"age"`
}

// Scan 从数据库中读取出来
func (i *Info) Scan(value interface{}) error {
  bytes, ok := value.([]byte)
  if !ok {
    return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value))
  }

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

// Value 存入数据库
func (i Info) Value() (driver.Value, error) {
  return json.Marshal(i)
}

//改正指针接受者 确实不行
//func (i *Info) Value() (driver.Value, error) {
//  return json.Marshal(i)
//}

type User struct {
  ID   uint
  Name string
  Info Info `gorm:"type:string"`
}

Scan和Value方法,一个是指针方法一个是值方法

二:数组类型
三:枚举
Go 复制代码
type Host struct {
  ID     uint
  Name   string
  Status string
}

func main() {
  host := Host{}
  if host.Status == "Running" {
    fmt.Println("在线")
  }
  if host.Status == "Except" {
    fmt.Println("异常")
  }
  if host.Status == "OffLine" {
    fmt.Println("离线")
  }
}

字符串硬编码

Go 复制代码
type Host struct {
  ID     uint
  Name   string
  Status string
}

const (
  Running = "Running"
  Except = "Except"
  OffLine = "OffLine"
) 

func main() {
  host := Host{}
  if host.Status == Running {
    fmt.Println("在线")
  }
  if host.Status == Except {
    fmt.Println("异常")
  }
  if host.Status == OffLine {
    fmt.Println("离线")
  }
}
Go 复制代码
type Host struct {
  ID     uint
  Name   string
  Status int
}

const (
  Running = 1
  Except  = 2
  OffLine = 3
)

func main() {
  host := Host{}
  if host.Status == Running {
    fmt.Println("在线")
  }
  if host.Status == Except {
    fmt.Println("异常")
  }
  if host.Status == OffLine {
    fmt.Println("离线")
  }
}

但是,如果返回数据给前端,前端接收到的状态就是数字,不过问题不大,前端反正都要搞字符映射的,因为要做颜色差异显示。

但是这并不是后端偷懒的理由 于是我们想到,在json序列化的时候,根据映射转换回去

Go 复制代码
type Host struct {
  ID     uint   `json:"id"`
  Name   string `json:"name"`
  Status int    `json:"status"`
}

func (h Host) MarshalJSON() ([]byte, error) {
  var status string
  switch h.Status {
  case Running:
    status = "Running"
  case Except:
    status = "Except"
  case OffLine :
    status = "OffLine"
  }
  return json.Marshal(&struct {
    ID     uint   `json:"id"`
    Name   string `json:"name"`
    Status string `json:"status"`
  }{
    ID:     h.ID,
    Name:   h.Name,
    Status: status,
  })
}

const (
  Running = 1
  Except  = 2
  OffLine  = 3
)

func main() {
  host := Host{1, "枫枫", Running}
  data, _ := json.Marshal(host)
  fmt.Println(string(data)) // {"id":1,"name":"枫枫","status":"Running"}
}

这样写确实可以实现我们的需求,但是根本就不够通用,凡是用到枚举,都得给这个Struct实现MarshalJSON方法

类型别名

Go 复制代码
type Status int

func (status Status) MarshalJSON() ([]byte, error) {
  var str string
  switch status {
  case Running:
    str = "Running"
  case Except:
    str = "Except"
  case OffLine:
    str = "Status"
  }
  return json.Marshal(str)
}

type Host struct {
  ID     uint   `json:"id"`
  Name   string `json:"name"`
  Status Status `json:"status"`
}

const (
  Running Status = 1
  Except  Status = 2
  OffLine Status = 3
)

func main() {
  host := Host{1, "枫枫", Running}
  data, _ := json.Marshal(host)
  fmt.Println(string(data)) // {"id":1,"name":"枫枫","status":"Running"}
}

嗯,代码简洁了不少,在使用层面已经没有问题了

但是,这个结构体怎么表示数据库中的字段呢?

golang中没有枚举

我们只能自己通过逻辑实现枚

相关推荐
cuisidong199727 分钟前
5G学习笔记三之物理层、数据链路层、RRC层协议
笔记·学习·5g
乌恩大侠29 分钟前
5G周边知识笔记
笔记·5g
南宫理的日知录35 分钟前
99、Python并发编程:多线程的问题、临界资源以及同步机制
开发语言·python·学习·编程学习
数据与后端架构提升之路1 小时前
从神经元到神经网络:深度学习的进化之旅
人工智能·神经网络·学习
一行12 小时前
电脑蓝屏debug学习
学习·电脑
咔叽布吉2 小时前
【论文阅读笔记】CamoFormer: Masked Separable Attention for Camouflaged Object Detection
论文阅读·笔记·目标检测
johnny2332 小时前
《大模型应用开发极简入门》笔记
笔记·chatgpt
亦枫Leonlew2 小时前
微积分复习笔记 Calculus Volume 1 - 4.7 Applied Optimization Problems
笔记·数学·微积分·1024程序员节
小肥象不是小飞象2 小时前
(六千字心得笔记)零基础C语言入门第八课——函数(上)
c语言·开发语言·笔记·1024程序员节
星LZX2 小时前
WireShark入门学习笔记
笔记·学习·wireshark