Go语言如何正确实现枚举?答案隐藏在官方源码中。转载本文请联系网管谢bi公众号。在编程领域,枚举用于表示只包含有限数量固定值的类型。它通常用于识别开发中的错误代码或状态机。以实体对象的状态机为例,它通常对应于标识该对象在数据库中对应记录状态的字段值。刚开始学习编程的时候,肯定写过或者至少看过直接使用幻数进行判断的代码。什么是幻数?比如你想置顶一篇文章,首先要判断这篇文章是否已经发表。if(article.state==2){//state2表示文章已经发表}如果我们的代码里没有注释,或者当我们项目的代码里全是这些幻数的判断时,你会不会头疼?后来学会了把这些状态值定义为常量,还做了一个判断对象状态的方法来单独封装这个逻辑。publicclassArticleState{publicstaticfinalintDraft=1;//草稿publicstaticfinalintPublished=2;//发布publicstaticfinalintDeleted=3;//删除}publicBooleancheckArticleState(intstate){...}这种用法肯定比直接在程序中使用幻数来判断要好得多好多了,至少看起来不头疼了,你也别想骂我了。不过当时带我的大哥说这个方法也有缺点。上面的checkArticleState方法用于检查文章的状态。初衷是让调用者传入ArticleState的三个静态常量之一。语法上也允许传入任何int值,编译器不会发出任何警告。改用枚举更合适。嗯~!我不记得在大学教Java的那个学期老师讲过这个东西。会不会是我上课玩手机又错过了一个知识点?...所以在使用了枚举之后,我们的Java代码就变成了://使用enum而不是class来声明publicenumArticleState{//来创建所有的枚举对象inenumDraft(1,"draft");Published(2,"Published");Deleted(3,"Deleted")//自定义属性privateintcode;privateStringtext;//构造方法必须是privateArticleState(intcode,Stringtext){this.code=id;this.text=name;}}publicBooleancheckArticleState(ArticleStatestate){...}这样依靠枚举类型的形参帮助我们过滤掉非法的状态值。当一个整数值作为参数传递给checkArticleState方法时,由于类型不匹配而无法编译,编译器可以在编写代码时立即提示。如果您从未使用过Java,则不必担心。我已经用注释标记了主要的语法点。后来这两年主要是用Go做项目。我发现Go也存在类似的问题,但是Go并没有提供枚举类型,那么如何适当的限制state值呢?如果你仍然使用int类型的常量,你必须不。例如:const(Draftint=1Published=2Deleted=3)const(Summerint=1Autumn=2Winter=3Spring=4)funcmain(){//输出true,不会有编译错误fmt.Println(Autumn==Draft)}例如上面定义了两组int类型的常量,一组代表文章的状态,一组代表季节的四个季节。这样比较文章状态和季节不会有任何编译错误。答案可以在Go内置库的代码中找到,也可以在我们都知道的一些开源库中找到。比如看看google.golang.org/grpc/codes中gRPC的错误码是如何定义的,我们马上就能明白如何正确实现枚举。下面我就不大惊小怪了,直接贴出答案。不想看源码里的,看我这里写的就可以了,都是这么搞的。我们可以使用int作为基本类型来创建别名类型。Go支持这种类型的Seasonintconst(SummerSeason=1Autumn=2Winter=3Spring=4)。当然,Go在定义连续常量值时经常使用iota,所以上面的定义还可以进一步简化。typeSeasonintconst(SummerSeason=iota+1AutumnWinterSpring)typeArticleStateintconst(DraftArticleState=iota+1PublishedDeleted)funccheckArticleState(ArticleStatestate){//...}funcmain(){//两个操作数类型不匹配,编译错误fmt.Println(Autumn==draft)//参数类型不匹配,编译错误checkArticleState(100)}虽然这些状态值的底层类型都是int值,但是无论是比较两个不相关类型的枚举值还是使用整型值调用checkArticleState方法作为检查文章状态的参数会导致编译错误,因为现在我们在使用状态值的地方有类型限制。这就是为什么对于错误码、状态机等状态值数量有限的场景,不能使用整型常量而是使用枚举。虽然Go语言没有像Java那样提供单独的枚举类型来表示枚举,但是我们仍然可以通过创建类型别名来实现枚举。你学会了吗?(#^.^#)
