在 Go 如何实现枚举?

Go 语言并没有 enum 关键字,在Protobuf中,Go 语言只是 ”有限的枚举“ 支持,我们也会用常量来定义,枚举值也需要有字面意思的映射。

示例

通过定义常量来定义枚举类型,如:

1
2
3
4
5
6
7
8
9
10
11
type OperateType int

const (
INSERT OperateType = iota
UPDATE
DELETE
)

func main() {
fmt.Println(INSERT, UPDATE, DELETE)
}

此时,打印定义的常量,就可以获取到对应的类型。但如何获取到类型对应的描述呢?通过自定义实现Stringer接口来实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type OperateType int

const (
INSERT OperateType = iota
UPDATE
DELETE
)

func (o OperateType) String() string {
return [...]string{"INSERT", "UPDATE", "DELETE"}[o]
}

func main() {
fmt.Println(INSERT)
}
// 打印出: INSERT

String 方法在字符串输出时会自动调用该方法。

自动生成 String

利用官方提供的 cmd/string 来快速自动实现。

安装如下命令:

1
go install golang.org/x/tools/cmd/stringer@latest

在所需枚举值上设置 go:generate 指令:

1
2
//go:generate stringer -type=OperateType
type OperateType int

在项目根目录执行:

1
go generate ./...

会在根目录生成 fishtype_string.go 文件:

1
2
3
4
5
.
├── fishtype_string.go
├── go.mod
├── go.sum
└── main.go

fishtype_string 文件内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import "strconv"

func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[INSERT-0]
_ = x[UPDATE-1]
_ = x[DELETE-2]
}

const _OperateType_name = "INSERTUPDATEDELETE"

var _OperateType_index = [...]uint8{0, 6, 12, 18}

func (i OperateType) String() string {
if i < 0 || i >= OperateType(len(_OperateType_index)-1) {
return "OperateType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _OperateType_name[_OperateType_index[i]:_OperateType_index[i+1]]
}

自动实现了Stringer接口

在main中,输出INSERT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import "fmt"

//go:generate stringer -type=OperateType
type OperateType int

const (
INSERT OperateType = iota
UPDATE
DELETE
)

func main() {
fmt.Printf("insert type = %d\n", INSERT)
fmt.Printf("insert desc = %s\n", INSERT)
}

执行

1
go run .

输出:

1
2
insert type = 0
insert desc = INSERT

参考

Search by:GoogleBingBaidu