您好,欢迎访问一九零五行业门户网

伙计,Go项目怎么使用枚举?

前言枚举是一种很重要的数据类型,在java、c语言等主流编程语言中都支持了枚举类型,但是在go语言中却没有枚举类型,那有什么替代方案吗?本文我们来聊一聊这个事情;
为什么要有枚举我们以java语言为例子,在jdk1.5之前没有枚举类型,我们通常会使用int常量来表示枚举,一般使用如下:
public static final int color_red = 1;public static final int color_blue = 2;public static final int color_green = 3;
使用int类型会存在以下隐患:
不具备安全性,声明时如果没有使用final就会造成值被篡改的风险;语义不够明确,打印int型数字并不知道其具体含义于是乎我们就想到用常量字符来表示,代码就变成了这样:
public static final string color_red = "red";public static final string color_blue = "blue";public static final string color_green = "green";
这样也同样存在问题,因为我们使用的常量字符,那么有些程序猿不按套路出牌就可以使用字符串的值进行比较,这样的代码会被不断模仿变得越来越多的,然后山就出现了;
所以我们迫切需要枚举类型的出现来起到约束的作用,假设使用一个枚举类型做入参,枚举类型就可以限定沙雕用户不按套路传参,这样就可以怼他了,哈哈~;
使用枚举的代码就可以变成这样,传了枚举之外的类型都不可以了;
public class enumclass { public static void main(string [] args){ color color = color.red; convert(color); system.out.println(color.name()); } public static void convert(color c){ system.out.println(c.name()); }}enum color{ red,blue,green;}
go语言就没有枚举类型,我们该使用什么方法来替代呢?
定义新类型实现枚举枚举通常是一组相关的常量集合,go语言中有提供常量类型,所以我们可以使用常量来声明枚举,但也同样会遇到上述的问题,起不到约束的作用,所以为了起到约束我们可以使用go语言另外一个知识点 -- 类型定义,go语言中可以使用type关键字定义不同的类型,我们可以为整型、浮点型、字符型等定义新的类型,新的类型与原类型转换需要显式转换,这样在一定程度上也起到了约束的作用,我们就可以用go语言实现如下枚举:
type orderstatus intconst ( create orderstatus = iota + 1 paid delivering completed cancelled)func main() { a := 100 iscreated(a)}
上面的代码就会报错:
./main.go:19:12: cannot use a (variable of type int) as type orderstatus in argument to iscreated
定义新的类型可以起到约束作用,比如我们要检查状态机,入参限定了必须是orderstatus类型,如果是int类型就会报错。
上面我们的枚举实现方式只能获取枚举值,获取不到其映射的字面意思,所以我们可以优化一下,实现string方法,使用官方提供的cmd/string来快速实现,代码如下:
//go:generate stringer -type=orderstatustype orderstatus intconst ( create orderstatus = iota + 1 paid delivering completed cancelled)
执行命令go generate ./...生成orderstatus_string.go文件:
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[create-1] _ = x[paid-2] _ = x[delivering-3] _ = x[completed-4] _ = x[cancelled-5]}const _orderstatus_name = "createpaiddeliveringcompletedcancelled"var _orderstatus_index = [...]uint8{0, 6, 10, 20, 29, 38}func (i orderstatus) string() string { i -= 1 if i < 0 || i >= orderstatus(len(_orderstatus_index)-1) { return "orderstatus(" + strconv.formatint(int64(i+1), 10) + ")" } return _orderstatus_name[_orderstatus_index[i]:_orderstatus_index[i+1]]}
protobuf中生成的枚举代码go语言使用protobuf会生成对应的枚举代码,我们发现其中也是使用定义新的类型的方式来实现的,然后在封装一些方法,我们来赏析一下protobuf生成的枚举代码:
const ( created orderstatus = 1 paid orderstatus = 2 canceled orderstatus = 3)var orderstatus_name = map[int32]string{ 1: "created", 2: "paid", 3: "canceled",}var orderstatus_value = map[string]int32{ "created": 1, "paid": 2, "canceled": 3,}func (x orderstatus) enum() *orderstatus { p := new(orderstatus) *p = x return p}func (x orderstatus) string() string { return proto.enumname(orderstatus_name, int32(x))}func (x *orderstatus) unmarshaljson(data []byte) error { value, err := proto.unmarshaljsonenum(orderstatus_value, data, "orderstatus") if err != nil { return err } *x = orderstatus(value) return nil}
总结虽然go语言没有提供枚举类型,但是我们也可以根据go语言的两个特性:常量和定义新类型来实现枚举,方法总比困难多吗,开源库是优秀的,我们往往可以从高手那里里学习很多,记住,请永远保持一个学徒之心;
以上就是伙计,go项目怎么使用枚举?的详细内容。
其它类似信息

推荐信息