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 = 1Published = 2Deleted = 3)const (Summer int = 1Autumn = 2Winter = 3Spring = 4)func main() {// 输出 true, 不会有任何编译错误fmt.Println(Autumn == Draft)}
比如上面定义了两组 int 类型的常量,一类代表文章状态,一类代表季节的四季。这种方式拿文章状态与季节进行比较不会有任何编译上的错误。
答案在 Go 内置库或者一些咱们都知道的开源库的代码里就能找到。比如看看 google.golang.org/grpc/codes 里的gRPC 的错误码是怎么定义的,我们马上就能明白该怎么正确的实现枚举。
下面不多卖关子直接上答案了,不想去源码里看的,就看我这里写的也行,都是这么做的。
我们可以用 int 作为基础类型创建一个别名类型,Go 里边是支持这个的
type Season intconst (Summer Season = 1Autumn = 2Winter = 3Spring = 4
)
当然定义连续的常量值的时候 Go 里边经常使用 iota,所以上面的定义还能进一步简化。
type Season intconst (Summer Season = iota + 1AutumnWinterSpring
)type ArticleState intconst (Draft ArticleState = iota + 1PublishedDeleted
)func checkArticleState(ArticleState state) {// ...
}func main() {// 两个操作数类型不匹配,编译错误fmt.Println(Autumn == Draft)// 参数类型不匹配,编译错误checkArticleState(100)}
虽然这些状态值的底层的类型都是 int 值,但是现在不论是进行两个不相干类型的枚举值比较,还是用整型值作为参数调用 checkArticleState 方法检查文章状态,都会造成编译错误,因为现在我们使用状态值的地方都有了类型限制。
这就是为什么针对错误码、状态机这种涉及有限数量状态值的场景下不能用整型常量而是要用枚举的原因。虽然 Go 语言里没有像 Java 一样单独提供一个 enum 表示枚举的类型,但是我们仍然能通过创建类型别名来实现枚举。
你学会了吗?(#^.^#)
- END -
扫码关注公众号「网管叨bi叨」
给网管个星标,第一时间吸我的知识
Go 语言里怎么正确实现枚举?答案藏着官方的源码里相关推荐
- c语言远控,远控鼠标!C语言简单编程:整舍友必备+附送实例源码!
远控鼠标!C语言简单编程:整舍友必备+附送实例源码!-1.jpg (10.71 KB, 下载次数: 0) 2018-10-11 05:24 上传 关注<一碳科技>有更多干货等着你哦! 远控 ...
- Kotlin 源码里成吨的 noinline 和 crossinline 是干嘛的?看完这个视频你转头也写了一吨...
视频先行 扫码看视频吧! 然后下面的就不用看了 或者--你喜欢看文字? Kotlin 里有个特别好用的关键字叫 inline,它可以帮你对做了标记的函数进行内联优化.所谓内联就是,调用的函数在编译的时 ...
- Go 源码里的这些 //go: 指令,go:linkname 你知道吗?
原文地址: Go 源码里的这些 //go: 指令,你知道吗? 一文解惑 //go:linkname 指令
- 源码里查看Android版本
源码里查看Android版本:build/core/version_defaults.mk
- c语言比较函数memcmp,c语言函数memcmp()如何比较内存前n个字节实例源码介绍
c语言函数memcmp()如何比较内存前n个字节实例源码介绍.引入头文件:#include 定义memcmp()函数:int memcmp (const void *s1, const void *s ...
- 如何在php直播平台源码里实现“查询附近主播”功能
在php直播平台源码中,"发现同城主播"的功能是如何开发出来的?下面给大家介绍附近功能中的距离之间的换算,通过本文,你可以: 理解如何在php直播平台源码里换算经纬度 理解发现同城 ...
- 39 解决全志h3 linux内核源码里的关于script.fex的bug
在script.fex里有关于io口的配置: Port:端口+组内序号<功能分配><内部电阻状态><驱动能力><输出电平状态>[gpio_para]gp ...
- c语言 feof_C语言 实现简单功能的12306火车售票系统【附源码】
本文福利在文末! 学习迷茫遇到问题了吗?现在关注微信公众号:C程序编程 免费获取进阶指导,资料工具以及源码 程序设计要求用C语言写一个简单的火车售票系统,主要实现的功能为: 录入班次信息 浏览班次信息 ...
- C语言零基础项目:打字母游戏!详细思路+源码分享
每天一个C语言小项目,提升自己的编程能力! <字母游戏>是一款有趣的打字游戏,可以提高你的打字速度. 今天就用C语言写了这么个打字母的小程序,就是以前学习机上那种字母往下掉,然后按相应键 ...
最新文章
- 交叉编译VIM并移植到ARM嵌入式Linux系统
- Redis:Redis集群实战
- 成员函数和友元函数实现一元运算符重载
- 3种Python数据结构,13种创建方法,这个总结,超赞!
- CODING 受邀参加《腾讯全球数字生态大会》
- 面试时遇到「看门狗」脖子上挂着「时间轮」,我就问你怕不怕?
- 如何用python画矿物分布地图_python怎么画出分布图?
- 用Python在地图上模拟疫情扩散
- mysql中问号传参_问号传值有以下三种方法:
- cym : BaseQuickAdapter.setOnItemChildClickListener失效点击没反应
- (FortiGate)飞塔防火墙快速初始化管理员密码
- 关于mobi书籍文件合并
- php 数组下标重新排,PHP使用array_merge重新排列数组下标的方法
- 【ChatGPT|AI 应用】ChatGPT + MindShow 快速制作 PPT
- JAVA系列:SimpleDateFormat解析带T字符的时间格式( yyyy-MM-ddTHH:mm:sssZ )
- 计算机网络网桥思维导图,《王道计算机网络》学习笔记总目录+思维导图
- 10款NFT游戏邀请的“玩赚”
- 2的n次方计算,支持大整数,nodejs代码
- 为什么期货投资70%的亏钱,20%不亏不赚,10%是赚钱?
- Android电话拨打流程源码分析
热门文章
- [linux]关于deepin截图软件在KDE桌面下无法使用粘贴的解决方法
- 以数据为中心的存储观
- 倒排索引-搜索引擎的基石
- rsync和inotify实时同步配置 exclude排除多个文件夹
- 翻译【ElasticSearch Server】第一章:开始使用ElasticSearch集群(2)
- Java 数据库连接池的技术选型都应考虑哪些要素
- 如何实现一个楼中楼的评论系统
- 模糊聚类算法(FCM)和硬聚类算法(HCM)的VB6.0实现及
- centos7下swoole1.9的安装与HttpServer的使用
- 未能正确加载“Microsoft.VisualStudio.Editor.Implementation.EditorPackage”包。