Go枚举

package main

import (
	"encoding/json"
	"log"
	"strings"
)

type Status int8

// 定义常量
const (
	UP Status = iota + 1 // 从1开始
	DOWN
	RUNNING
	PENDING
	ERROR
)

// StatusMap 也可以准备一个状态的字典,方便传输的时候转换,将状态与字符串对应
var StatusMap = map[Status]string{
	UP:      "UP",
	DOWN:    "DOWN",
	RUNNING: "RUNNING",
	PENDING: "PENDING",
	ERROR:   "ERROR",
}

// MarshalJSON 重写序列化方法,将原本数字替换成对应的字符串
func (s Status) MarshalJSON() ([]byte, error) {
	v, ok := StatusMap[s]
	if ok {
		return []byte(`"` + v + `"`), nil
	} else {
		return nil, nil
	}
}

// UnmarshalJSON 重写反序列化方法,将字符串反序列化为对应的数字
func (s *Status) UnmarshalJSON(data []byte) error {
	str := string(data)
	str = strings.Trim(str, `"`)
	for k, v := range StatusMap {
		if v == strings.ToUpper(str) {
			*s = k
			return nil
		}
	}
	return nil
}

// String 打印对应状态的时候,转换为对应的字符串
func (s Status) String() string {
	v, ok := StatusMap[s]
	if ok {
		return `"` + v + `"`
	}
	return ""
}

type test struct {
	Status Status
	A      string
}

func main() {
	// 直接打印,显示的也是对应的字符串
	log.Println(UP, DOWN, RUNNING) // "UP" "DOWN" "RUNNING"
	t1 := test{
		Status: UP,
		A:      "aaaa",
	}
	// 在对象中也可以看到是字符串
	log.Printf("%+v\n", t1) // {Status:"UP" A:aaaa}
	t2, err := json.Marshal(t1)
	if err != nil {
		log.Println(err)
		return
	}
	// 序列化之后的字符串中也是以字典中对应的字符串显示
	log.Println(string(t2)) // {"Status":"UP","A":"aaaa"}

	// 反序列化
	var b test
	err = json.Unmarshal([]byte(`{"Status":"down","A":"aaaa"}`), &b)
	if err != nil {
		log.Println(err)
		return
	}
	log.Println(b.Status == DOWN) // true
}

需要注意的是

  1. 这里实现的是 MarshalJSONUnmarshalJSON 方法,所以,这里只对在json中枚举字段的序列化和反序列化有效
  2. 反序列化的时候,传入的不是 int8 类型,而是应该传入对应的字符串
posted @ 2023-01-08 06:37  厚礼蝎  阅读(45)  评论(0)    收藏  举报