G

[Golang]Gorm框架 枚举

RoLingG 2023-11-23

枚举(可能写的有问题)

很多状态判断对与开发者而言都是有限的,例如:主机管理中,状态有 Running 运行中, OffLine 离线, Except 异常,存储为字符串,不仅是浪费空间,每次判断还要多复制很多字符,造成大量无用数据的同时增添维护成本。

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("离线")
   }
}

当然,应对方法也是有的,将这些常用的值存储下来,以便于后续使用的调用

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("离线")
   }
}

虽然代码变多了,但是维护方便了

但是数据库中存储的依然是字符串,浪费空间这个问题并没有解决。

所以可以再简化一点,用数字去进行状态的表示:

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序列化的时候,根据映射转换回去

package main

import (
   "encoding/json"
   "fmt"
)

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, "RoLingG", 1}
   data, _ := json.Marshal(host)
   fmt.Println(string(data)) // {"id":1,"name":"RoLingG","status":"Running"}
}

虽然能实现需求,但是不够通用,有别的类型使用都要重写json.Marshal的内容

type Status int

// 将(h host)改成(status Status),这样就不用每次在变化struct的方法时进行更改了
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"` //直接获取Status,通过传入的Status获取对应的int数据,直接识别状态,原先是获取string数据,还需要转化成int识别状态
}

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

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

实际在Gorm中的运用:

type Status int

func (s Status) MarshalJSON() ([]byte, error) {
   return json.Marshal(s.String())
}

func (s Status) String() string {
   var str string
   switch s {
   case Running:
      str = "Running"
   case Except:
      str = "Except"
   case OffLine:
      str = "Status"
   }
   return str
}

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

type Host struct {
   ID     uint   `json:"id"`
   Status Status `gorm:"size:8" json:"status"`
   IP     string `json:"ip"`
}

var DB *gorm.DB
var mysqlLogger logger.Interface

func init() {
   username := "root1"    //账号
   password := "rootroot" //密码
   host := "127.0.0.1"    //数据库地址,可以是Ip或者域名
   port := 3306           //数据库端口
   DBname := "GoORM"      //数据库名
   timeout := "10s"       //连接超时,10秒

   mysqlLogger = logger.Default.LogMode(logger.Info)

   // root:root@tcp(127.0.0.1:3306)/gorm?
   dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=%s", username, password, host, port, DBname, timeout)
   //连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
   db, err := gorm.Open(mysql.Open(dsn))
   if err != nil {
      panic("连接数据库失败, error=" + err.Error())
   }
   DB = db
   // 连接成功
}

func main() {
   //DB.AutoMigrate(&Host{})

   //DB.Create(&Host{
   // IP:     "192.168.200.12",
   // Status: Running,
   //})
   var host Host
   DB.Take(&host) //数据库内是这样{"id":1,"status":1,"ip":"192.168.200.12"}
   fmt.Println(host)
   fmt.Printf("%#v,%T\n", host.Status, host.Status)
   data, _ := json.Marshal(host)
   fmt.Println(string(data)) //但实际输出通过枚举将状态1转换成了对应的文字状态{"id":1,"status":"Running","ip":"192.168.200.12"}
}
PREV
[Golang]Gorm框架 关系操作
NEXT
[Golang基础语法] 基本数据类型

评论(0)

发布评论