Golang 枚举详解

2023-11-05

什么是枚举

枚举(Enumeration)是一种常见的编程概念,它定义了一组命名常量。我们知道在 Go 语言中定义常量是这样的形式:

const (
	A = "a"
	B = "b"

开发者可以使用枚举创建复杂的、有限的常量集,这些常量集具有有意义的名称和唯一的值。

枚举语法示例

在 Go 语言中,没有提供枚举类型,在 python、java、C++ 等语言中,提供了 enum 关键字来创建枚举类型。

但是 Go 语言可以利用 const + iota 实现枚举的效果,const 用来定义常量,[iota](https://github.com/golang/go/wiki/Iota) 是一个增数器,生成连续整数序列。

下面看看如何使用 const + iota 实现枚举

const (
	 Monday int = iota      // Monday  = 0
	 Tuesday               // Tuesday = 1
	 Wednesday             // Wednesday = 2
	 Thursday              // Thursday = 3
	 Friday                // Friday = 4
	 Saturday              // Saturday =5
	 Sunday                // Sunday = 6
)

可以发现 iota 生成了从 0 - 6 的整数序列分别作为常量名称的值。

枚举的使用疑问

对于刚接触枚举的,应该会有以下疑问:

枚举与常量的区别

从上面那个例子可以看出枚举好像就是定义了一堆整形常量而已。既然枚举就是定义常量,那为什么不直接使用 const 来定义常量呢?

首先看一下使用 const 来定义上面枚举实现的常量集:

const (
	 Monday     int = 0            // Monday  = 0
	 Tuesday    int = 1            // Tuesday = 1
	 Wednesday  int = 2            // Wednesday = 2
	 Thursday   int = 3            // Thursday = 3
	 Friday     int = 4            // Friday = 4
	 Saturday   int = 5            // Saturday =5
	 Sunday     int = 6            // Sunday = 6
)

可以发现使用 const 同样可以实现枚举的效果,但是没有枚举优雅。而且 const 并不能保证常量集的值是唯一的,比如 Wednesday int = 1 编译器也不会报错,但是程序可能会出现 Bug。通过使用枚举(const + iota),编译器层面保证了常量集里不会有相同的值。

枚举值的作用

通过上面枚举示例发现枚举包括:枚举名称( Monday )、枚举类型( int )、枚举值( 0 ),枚举名称、枚举类型很好理解,枚举值在编程中的有什么作用:

枚举本身的值没有什么意义,它是用来模拟现实中的某些只能取固定值的变量的,对应一个值只是在计算机中比较好处理。

枚举值只能为整形?

在枚举示例章节看到使用 iota 生成枚举值都是整数,在 Go 语言中枚举只能使用 iota ,所以枚举值只能是整数。

下面看一个 C++ 枚举示例:

//枚举类型必须是整形吗,不能是浮点数或是别的类型?
enum E
    {
        monday=-2,
        tuesday=1.5//有么有非int类型的枚举?
    };

上面的枚举值定义为负数、浮点数,这种写法是错误的。在任何语言中,枚举值只能是整形。

枚举高级用法

从 1 开始枚举

如果不希望枚举值从 0 开始,从1 开始,可以在 Go 这样实现:

const (
	 Monday = iota + 1     // Monday  = 1
	 Tuesday               // Tuesday = 2
	 Wednesday             // Wednesday = 3
	 Thursday              // Thursday = 4
	 Friday                // Friday = 5
	 Saturday              // Saturday = 6
	 Sunday                // Sunday = 7
)

自定义枚举值

iota 默认从 0 开始且依次递增 1,同时也可以使用数学运算自定义枚举值

const (
	 Monday = iota + 1     // Monday = 0 + 1 = 1
	 Tuesday = iota + 2    // Tuesday = 1 + 2 = 3
	 Wednesday = iota * 2  // Wednesday = 2 * 2 = 2
	 Thursday              // Thursday = 3
	 Friday                // Friday = 4
	 Saturday              // Saturday =5
	 Sunday                // Sunday = 6
)

通常不建议这么做,因为容易导致枚举值混乱且重复。
那么可能会有疑问,枚举不是说保证枚举值唯一吗?在其他语言中可以保证唯一,但是 Go 语言没有 enum 关键字,只能使用 iota 来模拟枚举,如果自己使用不当也会导致枚举值重复,比如上面的例子。

跳过值的枚举

如果想要跳过某个值,可以使用 _ 字符,即忽略的意思

const (
	 Monday = iota         // Monday = 0 
   _                     // 1 被跳过
	 Tuesday               // Tuesday = 2
	 Wednesday             // Wednesday = 3
	 Thursday              // Thursday = 4
   _                     // 5 被跳过
	 Friday                // Friday = 6
	 Saturday              // Saturday = 7
	 Sunday                // Sunday = 8
)

枚举使用场景

下面举例几个枚举的使用场景,加深枚举的作用和使用。

限制参数类型

当处理状态码时,如果不使用枚举

const (
	Normal       = 200
	Forbid       = 403
	NetworkError = 502
)

// 该函数形参是整形
func HandlerStatus(statusCode int) {
	fmt.Println(statusCode)
}

// 调用 HandlerStatus 随便什么整数都可以
func main() {
	HandlerStatus(Normal)
	HandlerStatus(404)
}

结果:
200
404

HandlerStatus 这个函数应该只能传 NormalForbidNetworkError 这三个常量,可以发现常量集之外的值也可以被正常调用,会使得程序不严谨。

下面看看使用枚举是否能达到效果?

虽然 Go 中并没有 enum 关键字来定义枚举类型,但是 Go 使用类型别名来定义枚举类型

// int 别名
type Code int

const (
	Normal Code = iota
	Forbid
	NetworkError
)

func HandlerStatus(statusCode Code) {
	fmt.Println(statusCode)
}

func main() {
	HandlerStatus(Normal)
	var notFount int = 1
	// 这里会导致程序编译失败,因为 notFount 不是 Code 类型
	HandlerStatus(notFount)
}

通过枚举就可以限制 HandlerStatus 的入参类型,保证程序的严谨。

使用 string 作为枚举值

我们知道 Go 语言使用 iota 生成连续整数作为枚举值,但是有的时候希望能描述枚举常量的意思,这个时候除了看枚举常量名称,也可以将枚举值转成 string 来达到效果。下面通过例子看看:

// 声明一个 week 类型
type week int

const (
	 Monday week = iota    // Monday  = 0
	 Tuesday               // Tuesday = 1
	 Wednesday             // Wednesday = 2
	 Thursday              // Thursday = 3
	 Friday                // Friday = 4
	 Saturday              // Saturday =5
	 Sunday                // Sunday = 6
)

func main() {
	var w week = Monday
	switch w {
	case Monday:
		fmt.Println(Monday)
	case Tuesday:
		fmt.Println(Tuesday)
	}
}

输出结果:
0

可以发现直接打印出了该枚举常量的枚举值 0,但是 0 并不是很容易理解该枚举常量的意义。

下面借助 Go 中 String 方法的默认约定,针对于定义了 String 方法的类型,默认输出的时候会调用该方法。

// 声明一个 week 类型
type week int

const (
	 Monday week = iota    // Monday  = 0
	 Tuesday               // Tuesday = 1
	 Wednesday             // Wednesday = 2
	 Thursday              // Thursday = 3
	 Friday                // Friday = 4
	 Saturday              // Saturday =5
	 Sunday                // Sunday = 6
)

// 实现 week 类型的 String() 方法
func (w week) String() string {
		return [...]string{"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"}[w]
}

func main() {
	var w week = Monday
	switch w {
	case Monday:
		fmt.Println(Monday)
	case Tuesday:
		fmt.Println(Tuesday)
	}
}

输出结果:
星期一

通过对枚举类型重写 String 方法,可以对枚举值进行自定义,可以清晰地描述该枚举变量的意义和作用。

总结

枚举定义了一组有限的常量集,像 C++、java 等语言有 enum 关键字来定义枚举类型,但是 Go 并没有提供枚举关键字来定义枚举类型,我们可以利用 const + iota 来达到枚举的效果。

同时很多开发者会忽略枚举的使用,因为枚举并不是必须使用的,完全可以直接常量来替代。但是枚举的使用提高程序可读性,严谨性等,所以在项目中使用枚举最好能够了解枚举的使用场景以及一些特定用法。

在这里插入图片描述
关注微信公众号,可了解更多云原生详情~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Golang 枚举详解 的相关文章

随机推荐

  • Selenium(一)2.第一个自动化测试脚本

    前面我们可以成功启动浏览器啦 接下来我们完成第一个自动化测试的脚本 举例 验证打开的链接是Selenium官网页面 分析问题 我们输入了一个url 然后打开网页 那么怎么确定这个页面是我们想要的页面呢 获取页面的url是不是与输入的一致 获
  • QT调用linux echo命令无效的解决方法

    问题 Qt中使用 QProcess execute echo 1 gt myFile 写文件 执行成功后 不生效 但是把打印出的命令放在终端里执行可以生效 原因 网上说 因为echo 是shell内建命令 必须使用如下形式 QProcess
  • 利用Excel数组公式统计各班优秀人数

    期末考试期间 教导处的阿明忙得不亦乐乎 不时地发出感叹 现在各班编在一起考试 统计优秀 及格 低分人数 真让人头疼 我知道他在操什么心 却心不在焉地说 countif函数你不是会用吗 会啊 但是 你看看 全年级各科成绩都在同一个工作表中 比
  • UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might b

    UserWarning This figure includes Axes that are not compatible with tight layout so results might be incorrect self figur
  • 虚拟机实现远程桌面连接

    目录 一 操作方法 二 连接成功 一 操作方法 首先点击控制面板 点击系统 点击改变设置 点击远程 选择允许连接 就可以 启用远程桌面 然后再命令提示符窗口输入 netstat a 查看启用远程桌面后打开的端口3389 表明其他计算机可以连
  • DetNet: A Backbone network for Object Detection 笔记

    Face 的lizeming大神注意到了现有Detection Network的两大通病 借用原本为了class而设计的network 牵强地附加上其他辅助结构来实现Detection 下采样能带来大感受野 从而提升class任务精度 但下
  • 华夏相机开发/臻识相机开发/车牌识别器开发对接使用总结

    最近做了款自助洗车小程序项目 需要用到车牌识别 华夏 臻识这两家相机均有使用 特此记录开发中的问题 1 初次使用 购买途径 当地购买的华夏相机T83 价格贵 且显示屏语音均无法使用 遂只对接了开闸 开发方式 因为自助洗车项目需要保持双端的及
  • PTA天梯赛的赛场安排

    天梯赛使用 OMS 监考系统 需要将参赛队员安排到系统中的虚拟赛场里 并为每个赛场分配一位监考老师 每位监考老师需要联系自己赛场内队员对应的教练们 以便发放比赛账号 为了尽可能减少教练和监考的沟通负担 我们要求赛场的安排满足以下条件 每位监
  • python爬虫需求分析-序:Python爬虫开发与数据分析简介

    爬虫是获取数据一种方式 能够按照一定规则自动抓取某个网站或者万维网信息的程序 现实环境中很大一部分网络访问都是由爬虫造成的 我们来看一个常见应用场景 当我们使用百度或者其他搜索引擎搜索某个关键字的时候 搜索结果中会包含对应的内容 比如 搜索
  • 游戏笔记本电脑推荐 多功能游戏本你见过吗?

    本来安排了一个国庆假期旅游计划 但是计划往往赶不上变化 被好朋友给 放鸽子 了 想着刚好我新买的游戏本到了 作为一个游戏宅 所以就打算呆在家玩玩游戏算了 结果不玩不知道 一玩上就爱不释手 现在甚至想将这款游戏笔记本电脑推荐给大家 它的名字叫
  • Windows主机信息搜集

    注意 一切内容仅用于信息技术分享 切勿用于其他用途 一切后果与作者无关 前言 通过命令执行使用cs拿到了内网的一台主机 接下来我们进行内网的信息搜集 1 内网环境分析 内网渗透 在拿到webshell的时候 想办法获取系统信息拿到系统权限
  • 四个/24地址块,试进行最大可能的聚合

    由于四个地址块前两个字节都相同 只需将每个地址块的第三个字节转换为二进制 212 56 132 0 24 212 56 10000100 0 212 56 133 0 24 212 56 10000101 0 212 56 134 0 24
  • C#控件命名规范

    类 型 前 缀 示 例 Adrotator adrt adrtTopAd BulletedList blst blstCity Button btn btnSubmit Calendar cal calMettingDates CheckB
  • nginx: [emerg] could not build the server_names_hash

    手头有块板子 上面起了nginx配置了多个域名 启动的时候发现报错 nginx emerg could not build the server names hash you should increase server names has
  • pandas中的时间序列

    一 夯实基础 datetime 模块中的数据类型 date 以公历形式存储日历日期 年月日 time 将时间存储为时分秒毫秒 datetime 存储日期和时间 timedelta 表示两个datetime值之间的差 日 秒 毫秒 1 获取当
  • 无效数据处理攻略: 如何从源头开始预防无效数据带来的风险

    数据处理在现代社会中变得越来越重要 而对于数据的可靠性和准确性 我们始终非常关注 然而 即使在对数据进行了精心管理的情况下 无效数据依然可能存在 并可能对数据分析和决策带来不良影响 因此 处理无效数据变得愈发重要 一 什么是无效数据 在处理
  • app数据分析体系 - 用户粘性 DAU,MAU 和 月人均活跃天数

    用户粘性指标 DAU MAU 月均活跃天数 DAU 和 MAU 日活跃用户占月活跃用户的比例越高 表明用户对App的使用粘性越高 DAU 即 Daily Active User 指日活跃用户数 MAU 即 Monthly Active Us
  • 后端进阶之路——深入理解Spring Security配置(二)

    前言 作者主页 雪碧有白泡泡 个人网站 雪碧的个人网站 推荐专栏 java一站式服务 前端炫酷代码分享 uniapp 从构建到提升 从0到英雄 vue成神之路 解决算法 一个专栏就够了 架构咱们从0说 数据流通的精妙之道 后端进阶之路 文章
  • A/B测试是什么?面试官把我问懵了!

    什么是A B测试 A B测试是为 web 或 app 界面或流程制作两个 A B 或多个版本 在同一时间维度 分别让组成成分相同 相似 的访客群组 目标人群 随机的访问这些版本 收集各群组的用户体验数据和业务数据 最后分析 评估出最好版本
  • Golang 枚举详解

    什么是枚举 枚举 Enumeration 是一种常见的编程概念 它定义了一组命名常量 我们知道在 Go 语言中定义常量是这样的形式 const A a B b 开发者可以使用枚举创建复杂的 有限的常量集 这些常量集具有有意义的名称和唯一的值