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中没有枚举

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

相关推荐
东方芷兰9 小时前
LLM 笔记 —— 02 大语言模型能力评定
人工智能·笔记·python·神经网络·语言模型·自然语言处理·cnn
charlie11451419110 小时前
理解C++20的革命特性——协程支持1
c++·学习·c++20·协程·语言特性·调度·现代c++
The_Killer.10 小时前
近世代数(抽象代数)详细笔记--群
学习·抽象代数·
阿明610 小时前
list模拟实现(简单版)【C++】
开发语言·c++·学习·list
Yupureki10 小时前
从零开始的C++学习生活 1:命名空间,缺省函数,函数重载,引用,内联函数
c语言·开发语言·c++·学习·visual studio
小墨宝11 小时前
web前端学习 langchain
前端·学习·langchain
9毫米的幻想11 小时前
【Linux系统】—— 程序地址空间
java·linux·c语言·jvm·c++·学习
71-311 小时前
C语言——循环的嵌套小练习
c语言·笔记·学习·其他
东方芷兰11 小时前
LLM 笔记 —— 03 大语言模型安全性评定
人工智能·笔记·python·语言模型·自然语言处理·nlp·gpt-3
悠哉悠哉愿意12 小时前
【ROS2学习笔记】Gazebo 仿真与 XACRO 模型
笔记·学习·机器人·ros2