Golang中如何实现枚举详析

Golang中如何实现枚举详析

Golang中怎么实现枚举?下面本篇文章给大家介绍一下Golang中实现枚举的方法,希望对大家有所帮助!

在编程领域里,枚举用来表示只包含有限数量的固定值的类型,在开发中一般用于标识错误码或者状态机。拿一个实体对象的状态机来说,它通常与这个对象在数据库里对应记录的标识状态的字段值相对应。

在编程领域里,枚举用来表示只包含有限数量的固定值的类型,在开发中一般用于标识错误码或者状态机。拿一个实体对象的状态机来说,它通常与这个对象在数据库里对应记录的标识状态的字段值相对应。【相关推荐:Go视频教程】

在刚开始学编程的时候,你一定写过,至少见过直接使用魔术数字进行判断的代码。啥叫魔术数字呢,举个例子,要置顶一个文章的时候先判断文章是不是已发布状态。

if (article.state == 2) {    // state 2 代表文章已发布 }

假如我们的代码里没有注释,或者等我们项目的代码里充斥着这些魔术数字的判断的时候,你是不是会很头疼?

后来我就学会了把这些状态值定义成常量,并且也搞一个判断对象状态的方法单独封装这段逻辑。

public class ArticleState {     public static final int Draft = 1; //草稿     public static final int Published = 2; //发布     public static final int Deleted = 3; // 已删除 } public  Boolean checkArticleState(int state) {     ... }

这种用法,肯定是比在程序里直接用魔术数字进行判断要强很多啦,至少看着不会很头疼,不会想骂**。

不过后来被当时带我的老大哥说这种也有缺点,上面这个 checkArticleState 方法用来检查文章状态,本意是让调用者传入 ArticleState 的三个静态常量之一,但由于没有类型上的约束,因此传入任意一个 int 值在语法上也是允许的,编译器也不会提出任何警告,用枚举更合适一些。

em~! 我不记得大学教 Java 的那个学期老师讲过这玩意啊,莫非又是一个上课玩手机错过的知识点?所以使用枚举后我们的Java代码变成了:

// 使用enum而非class声明 public enum ArticleState {     //要在enum里创建所有的枚举对象     Draft(1, "草稿");     Published(2, "已发布");     Deleted(3, "已删除")     // 自定义属性     private int code;     private String text;     // 构造方法必须是private的     ArticleState(int code, String text) {         this.code = id;         this.text = name;     } } public  Boolean checkArticleState(ArticleState state) {     ... }

这样就能靠形参的枚举类型帮我们过滤掉非法的状态值,把整型值作为参数传给 checkArticleState 方法时因为类型不匹配编译不过去,在写代码是编译器也能马上提示出来。

如果没有用过 Java 的小伙伴也不用纠结,主要语法点我用注释标注出来了,大家应该都能看懂。

后来这两年主要在用Go做项目,我发现相似的问题 Go 里存在,但是 Go 并没有提供枚举类型,那怎么做到进行状态值的正确限制呢?如果还是用 int 型的常量肯定不行。比如:

const (     Draft int = 1     Published = 2     Deleted   = 3 ) const (     Summer int = 1     Autumn     = 2     Winter     = 3     Spring     = 4 ) func main() {     // 输出 true, 不会有任何编译错误     fmt.Println(Autumn == Draft) }

比如上面定义了两组 int 类型的常量,一类代表文章状态,一类代表季节的四季。这种方式拿文章状态与季节进行比较不会有任何编译上的错误。

答案在 Go 内置库或者一些咱们都知道的开源库的代码里就能找到。比如看看 google.golang.org/grpc/codes 里的gRPC 的错误码是怎么定义的,就能明白该怎么正确的实现枚举。

我们可以用 int 作为基础类型创建一个别名类型,Go 里边是支持这个的

type Season int const (     Summer Season = 1     Autumn        = 2     Winter        = 3     Spring        = 4 )

当然定义连续的常量值的时候 Go 里边经常使用 iota,所以上面的定义还能进一步简化。

type Season int const (     Summer Season = iota + 1     Autumn     Winter     Spring ) type ArticleState int const (   Draft int = iota + 1   Published   Deleted  ) func checkArticleState(state ArticleState) bool {     // ... }  func main() {    // 两个操作数类型不匹配,编译错误    fmt.Println(Autumn == Draft)     // 参数类型不匹配,但是因为 ArticleState 底层的类型是 int 所以传递 int 的时候会发生隐式类型转换,所以不会报错    checkArticleState(100)  }

虽然这些状态值的底层的类型都是 int 值,但是现在进行两个不相干类型的枚举值比较,会造成编译错误,因为现在我们使用状态值的地方都有了类型限制。

不过函数 checkArticleState 的参数类型设置成了 ArticleState 但是因为 ArticleState 底层的类型是 int 。所以调用 checkArticleState 时传递 int 类型的参数会发生隐式类型转换,不会造成编译报错,这块如果想解决,只能重新定义类型来实现了

总结

到此这篇关于Golang中如何实现枚举的文章就介绍到这了,更多相关Golang实现枚举内容请搜索易知道(ezd.cc)以前的文章或继续浏览下面的相关文章希望大家以后多多支持易知道(ezd.cc)!

推荐阅读

    golang代理怎么设置

    golang代理怎么设置,代理,请求,设置,语言,客户端,应用程序,Go语言(或称Golang)是一种广受欢迎的编程语言,尤其适用于网络编程。在创建Web应用程序

    什么是golang

    什么是golang,语言,执行,编程语言,机器语言,高级语言,运行,golang是一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言;它可以在不损

    Java中的枚举类型

    Java中的枚举类型,枚举类型,常量,枚举,集合,方法,名称,Java是一种面向对象的编程语言,提供了丰富的语法和内置类型。Java中的枚举类型是一种特殊

    Golang之wait.Until 简单测试用例

    Golang之wait.Until 简单测试用例,结束,主程序,测试目的,验证wait.Until的用法 //测试wait.Until() 的用途package mainimport ( "fmt

    使用Golang实现简单Ping过程

    使用Golang实现简单Ping过程,报文,字节,摘要: Ping的基本原理是发送和接受ICMP请求回显报文,利用Go语言可以轻松实现这一过程,较之C/C++语言

    如何枚举JavaScript对象的属性?

    如何枚举JavaScript对象的属性?,如何枚举JavaScript对象的属性?,对象,属性,枚举,点这里,How do I enumerate the properties of a JavaScript

    使用NHibernate映射枚举集合

    使用NHibernate映射枚举集合,使用NHibernate映射枚举集合,映射,用于,属性,枚举,Mapping a collection of enums with NHibernate使用NHiber

    如何在Ruby中实现枚举?

    如何在Ruby中实现枚举?,如何在Ruby中实现枚举?,枚举,方法,用法,东西,How to implement Enums in Ruby?在Ruby中实现枚举用法的最佳方法是什么

    转发在C ++中声明一个枚举

    转发在C ++中声明一个枚举,转发在C ++中声明一个枚举,编译器,浏览,我已经,尝试,Forward declaring an enum in C++我正在尝试做类似以下的

    代表C#中参数化枚举的最佳方法?

    代表C#中参数化枚举的最佳方法?,代表C#中参数化枚举的最佳方法?,枚举,参数化,解决方案,我现在,Best way to represent a parameterized enum in