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

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

相关推荐
Ting丶丶35 分钟前
Electron入门笔记
javascript·笔记·electron
虾球xz1 小时前
游戏引擎学习第149天
人工智能·学习·游戏引擎
奕天者2 小时前
C++学习笔记(十七)——类之封装
c++·笔记·学习
亭墨2 小时前
linux0.11内核源码修仙传第六章——中断初始化
linux·c语言·驱动开发·学习·面试
好多大米2 小时前
[资源分享]-web3/区块链/学习路线/资料/找工作方式/水龙头
学习·web3·区块链
李长渊哦3 小时前
学习文章:Spring Boot 中如何使用 `@Async` 实现异步处理
java·spring boot·学习
李长渊哦4 小时前
学习文章:Spring Boot 中 Redis 配置与序列化管理
spring boot·redis·学习
你的微笑像拥抱4 小时前
HTTP 强 Etag 和 弱 Etag
笔记
zhuidushi44064 小时前
文献笔记 - A Survey on Aerial Swarm Robotics
笔记
WZF-Sang5 小时前
Linux——基础IO【3万字大章】
linux·服务器·c++·学习·文件系统·软硬链接·动态库静态库