Golang实现类似Java的复杂一点的枚举

168 阅读1分钟

为了让参数简洁一些,用到了反射

  1. 定义枚举结构体,包含编码和名称两个字段,定义一个map用来保存code->enum的映射关系
type Enum struct {
	Code string
	Name string
}

var enumMap map[reflect.Type]map[string]*Enum = make(map[reflect.Type]map[string]*Enum)
  1. 定义枚举初始化和解析函数

func storeEnum[T any](code string, enum *T) {
	typ := reflect.TypeOf(*enum)
	if _, ok := enumMap[typ]; !ok {
		enumMap[typ] = make(map[string]*Enum)
	}

	enumMap[typ][code] = (*Enum)(unsafe.Pointer(enum))
}

func InitEnum[T any](code string, name string) *T {
	enum := (*T)(unsafe.Pointer(&Enum{code, name}))
	storeEnum(code, enum)
	return enum
}

func ParseEnum[T any](code string) *T {
	var enum T
	typ := reflect.TypeOf(enum)

	if _, ok := enumMap[typ]; !ok {
		return nil
	}

	if _, ok := enumMap[typ][code]; !ok {
		return nil
	}

	return (*T)(unsafe.Pointer(enumMap[typ][code]))
}
  1. 使用方法
// 初始化
type ISP Enum
var (
    CMCC = InitEnum[ISP]("cmcc", "中国移动")
    CUCC = InitEnum[ISP]("cucc", "中国联通")
    CTCC = InitEnum[ISP]("ctcc", "中国电信")
)

// 根据字符串解析
isp := ParseEnum[ISP]("cmcc")
fmt.Println(isp)