Go语言学习——三分钟看透iota
源起枚举
最近做需求时,有一个需要枚举的场景,大概有10+个枚举类型,不愿意像定义一个开关那样敷衍的写成
const (
SwitchOff = 0
SwitchOn = 1
)
显得不够精致~
于是想到了iota,深入了解了下,这个小东西好像有点东西。
再回到需求本身——枚举。有了iota,就不用显示定义一大堆数值了。
未使用iota版本
const (
ColorRed = 0
ColorOrange = 1
ColorYellow = 2
ColorGrassland = 3
ColorCyan = 4
ColorBlue = 5
ColorPurple = 6
)
使用iota版本
const (
ColorRed = iota
ColorOrange
ColorYellow
ColorGrassland
ColorCyan
ColorBlue
ColorPurple
)
两者的效果是一样的,各个枚举对应的值也是一样的。iota是从0开始,每一行都是往下递增。乍一看,iota还显得挺高端。
施展威力的同时,iota也有大家诟病的地方。
比如这时候如果需要添加一个"灰色"的枚举类型,在未使用iota版本里面不管在什么位置插入这个枚举,定义一个具体数值即可,比如对应7。
在使用iota版本里面如果加在ColorPurple后面,对应的值就是7,没有问题。
但是如果在其他位置,那就会打破原来的平衡,比如放在ColorGrassland后
const (
ColorRed = iota // 0
ColorOrange // 1
ColorYellow // 2
ColorGrassland // 3
ColorGray // 4
ColorCyan // 5
ColorBlue // 6
ColorPurple // 7
)
可以看出,从加入ColorGray后,从ColorCyan开始以及后面的枚举对应的值都变了。如果各个枚举的值在代码中已经hard code了,那这样的调整将是灾难性的。
iota虽然灵活,但似乎有点过于灵活了。
看到这,你以为你已经了解了iota,不,你没有,它比你想的还要灵活、复杂。
iota的花式玩法
首先来看一道送分题
const (
AA = iota
BB
_
DD
)
问题
此时DD对应的值是多少?
稍稍推理下,显然不是2,因为中间还多了个下划线。
没错,DD对应的值是3。这里的下划线"_"表示跳过某值,原本对应在这个位置的值应该是2,但是获取它不重要,所以使用下划线跳过了,这个用法也和Go对应下划线的定义保持一致。
比如遍历map集合,不需要使用key值时,可以写成
for _, value := range testMap {
fmt.Println(value)
}
好,再看下一题
const (
AA = iota
BB
_
DD = iota + 1
EE
)
问题
此时DD和EE对应的值是多少?
与上例不同,这里在DD后面重新指定了DD = iota + 1,即在原有的数据上加1,所以此时DD的值为3+1=4。
后面EE没有重新定义,则也会顺延DD的规则递增1,即5。
如果上面一题你得到了正确的答案,那下面一题也不就不难了
const (
AA = iota
BB
_
DD = iota + 1
EE
FF = iota + 2
GG = iota
)
问题
此时FF和GG对应的值是多少。
根据上一题,DD和EE分别对应4和5。
首先看这里的FF,注意这里的FF并不是顺延EE的值加1,然后再加2,如果是顺延则FF = 6 + 2 = 8。但是FF的值是7。
每当某个枚举被重置(即后面使用iota重新赋值时),则需要从第一个枚举数到当前的次序,比如这里从AA=0数到FF,此时FF的次序是5,然后再加2,即FF=5+2=7。
GG的值使用上面的方法,得到值为6。
注意:以上是我从结果反推得到的结论,一开始难以理解这里各个枚举对应的值,找到这个规则后,发现程序跑出来值和规则验证的一样。
下面看最后一道题
const (
AA, BB = iota + 1, iota + 2
CC, DD
)
问题
此时的AA、BB、CC和DD对应的值分别是多少
这里只需要明白一个规则,iota是每行才会加一。
所以这里第一行的iota都是0,则AA和BB对应的值分别是0+1=1和0+2=2。
下面的CC和DD都是顺延,对应的iota递增则为1,然后分别按照iota+1和iota+2的运算得到值为1+1 = 2和1+2 = 3。
好了,做完上面不管是送分题还是送命题,我想,你对iota这个小东西算是有一个真正的了解。
个人感觉,功能实现千万条,看懂再用第一条。
回到枚举
有时候我们使用枚举,不仅是定义它的值,还需要有对应的描述信息,我们知道这在Java里面是比较方便实现的,毕竟Java本来就有枚举的概念。
下面我们看看Go实现带有描述信息枚举的两种方式。
使用map映射
const (
ColorRed = iota
ColorOrange
ColorYellow
ColorGrassland
ColorCyan
ColorBlue
ColorPurple
) var ColorMap = map[int]string{
ColorRed: "赤",
ColorOrange: "橙",
ColorYellow: "黄",
ColorGrassland: "绿",
ColorCyan: "青",
ColorBlue: "蓝",
ColorPurple: "紫",
}
这样,如果想获取ColorRed对应的描述信息,就可以写成ColorMap[ColorRed]。
定义枚举类型
type Color int
const (
ColorRed Color = iota
ColorOrange
ColorYellow
ColorGrassland
ColorCyan
ColorBlue
ColorPurple
) func (c Color) String() string {
switch c {
case ColorRed:
return "赤"
case ColorOrange:
return "橙"
case ColorYellow:
return "黄"
case ColorGrassland:
return "绿"
case ColorCyan:
return "青"
case ColorBlue:
return "蓝"
case ColorPurple:
return "紫"
}
将颜色枚举定义为Color类型,则所有枚举值都是该类型,如果要获取ColorRed对应的描述信息,就可以写成ColorRed.String()。
这种方式看着更加优雅,也更有Go的味道~
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!如果您想持续关注我的文章,请扫描二维码,关注JackieZheng的微信公众号,我会将我的文章推送给您,并和您一起分享我日常阅读过的优质文章。
Go语言学习——三分钟看透iota的更多相关文章
- Dart语言学习(三)Dart数值型
一.类型 数值型有 num,int, double num a = ; a = 12.5; print(a); print(a.runtimeType); ; // b = 20.5; print( ...
- Go语言学习笔记三: 常量
Go语言学习笔记三: 常量 定义常量 常量就是在声明后不能再修改的量. const x int = 100 const y string = "abc" const z = &qu ...
- PHP语言学习之php-fpm 三种运行模式
本文主要向大家介绍了PHP语言学习之php-fpm 三种运行模式,通过具体的内容向大家展示,希望对大家学习php语言有所帮助. php-fpm配置 配置文件:php-fpm.conf 开启慢日志功能的 ...
- Swift语言学习(三)基础操作符
操作符是用于检测.更改或者组合值的特殊符号或短语.例如,加法操作符 (+) 将两个数字加到一起 (如 let i = 1 + 2).更复杂的例子包括逻辑与操作符 && (如 if en ...
- 技能获取与C语言学习情况
你有什么技能比大多人(超过90%以上)更好? 仔细回想了一下自己到目前为止的学习生涯,好像真的没有什么技能能够比90%以上的人好. 初中高中学过很多东西,但是能够算得上专精的却着实没有.小学参加过计算 ...
- 12天学好C语言——记录我的C语言学习之路(Day 3)
12天学好C语言--记录我的C语言学习之路 Day 3: 不知不觉到了第三天的学习,我们前两天学习的东西很杂乱,各个方面都有学习.我觉得这不是不系统,也不是学的不扎实,这种学习对于初学者而言我认为是很 ...
- Go语言学习笔记(1)——顺序编程
Go语言学习笔记这一堆主要是<Go语言编程>(人民邮电出版社)的读书笔记.中间会穿插一些零碎的点,比如源码学习之类的.大概就是这样吧. 1. 顺序编程 1.1 变量 变量的声明: var ...
- C语言学习 第七次作业总结
C语言学习 第七次作业总结 数组可以分为数组和多下标数组(在传统的国内C语言书本中,将其称为二/多维数组). 数组名称 在之前的课程中,大家应该都有印象,对于int a这样的定义,会为变量 a 声明一 ...
- 技能收获与C语言学习
你有什么技能比大多人(超过90%以上)更好? 我会的东西很多,喜欢的东西太多,但是很遗憾广而不专,会而不精.学了很多东西我都是为了娱乐,因为以前我们那里过于强调学习,很多爱好也都被扼杀在摇篮里.我觉得 ...
随机推荐
- day13_7.15 迭代器和生成器
1.迭代器 迭代就是一个更新换代的过程,每次迭代都必须基于上一次的结果. 迭代器就是迭代取值的工具.举个例子: while True: print('循环输出') 此代码会无限循环输出文字,是个死循环 ...
- 使用java2Word生成Word文档打不开报错 存在非法字符xml
今天也不知道是该吐槽Java2word还是我的eclipse,总之就是使用Java2Word生成文档的时候文档生成没问题,但是生成的Word文档打不开还报错,存在非法字符xml,好扎心.终于找到了解决 ...
- Spring Boot中以代码方式配置Tomcat
在Spring Boot2.0以上配置嵌入式Servlet容器时EmbeddedServletContainerCustomizer类不存在,经网络查询发现被WebServerFactoryCusto ...
- leetcode14最长公共前缀
class Solution { public: string longestCommonPrefix(vector<string>& strs) { ) return " ...
- 7.Vue的计算属性
1.什么是计算属性 computed:计算属性的重点突出在 属性 两个字上(属性是名词),首先它是个 属性 其次这个属性有 计算的能力(计算是动词),这里的 计算 就是个函数:简单点说,它就是一个能够 ...
- 知识点总结 VUE部分
1.v-show和v-if的区别 v-show 操作的是元素的display属性 v-if 操作的是元素的创建和插入 v-if有更高的开销,而v-show有更高的初始渲染开销,如果需要非常频繁的切换, ...
- Asp.Net Core 中的环境变量
Asp.Net Core 中的环境变量 软件开发环境在大多数软件开发组织中,我们通常具有以下开发环境. 开发环境--Development 演示(模拟.临时)环境--Staging 生产环境-- Pr ...
- MySQL实战45讲学习笔记:第十六讲
一.今日内容概要 在你开发应用的时候,一定会经常碰到需要根据指定的字段排序来显示结果的需求.还是以我们前面举例用过的市民表为例,假设你要查询城市是“杭州”的所有人名字,并且按照姓名排序返回前 1000 ...
- Web协议详解与抓包实战:HTTP1协议-如何管理跨代理服务器的长短连接?(4)
一.HTTP 连接的常见流程 二.从 TCP 编程上看 HTTP 请求处理 三.短连接与长连接 四.Connection 仅针对当前连接有效 五.代理服务器对长连接的支持 未设置代理服务器 设置代理 ...
- [LeetCode] 911. Online Election 在线选举
In an election, the i-th vote was cast for persons[i] at time times[i]. Now, we would like to implem ...
