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

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

相关推荐
头疼的程序员7 分钟前
计算机网络:自顶向下方法(第七版)第八章 学习分享(三)
网络·学习·计算机网络
_李小白42 分钟前
【OSG学习笔记】Day 37: NodeVisitor(顶点访问器)
笔记·学习
程序员雷欧1 小时前
大模型应用开发学习第八天
大数据·人工智能·学习
SccTsAxR1 小时前
算法基石:手撕离散化、递归与分治
c++·经验分享·笔记·算法
晓晓hh2 小时前
JavaSE学习——set集合和Map映射
学习
西梅汁2 小时前
C++ 观察者模式
笔记
لا معنى له3 小时前
Var-JEPA:联合嵌入预测架构的变分形式 —— 连接预测式与生成式自监督学习 ----论文翻译
人工智能·笔记·学习·语言模型
世人万千丶3 小时前
Flutter 框架跨平台鸿蒙开发 - 宠物语言翻译器应用
学习·flutter·华为·开源·harmonyos·鸿蒙
AI成长日志3 小时前
【笔面试算法学习专栏】哈希表基础:两数之和与字母异位词分组
学习·算法·面试
"菠萝"3 小时前
C#知识学习-021(文字关键字)
开发语言·学习·c#