Go 语言, 一文彻底搞懂 iota 实现原理
我们知道,iota 常用于 const 表达式中,它的值是从 0 开始,每增加一行,iota 值 +1。
iota 可以简化常量定义,其规则我们慢慢介绍,先来几道热身题看看诸位对 iota 的理解程度。
题目
下面每个常量值为多少?
代码源于日志模块,LOG_EMERG 值为 0,下面每个常量递增 1。
下面每个常量值为多少?
代码源于 Go 互斥锁 Mutex 的实现,用于指示各种状态位的地址偏移。
答案:
下面每个常量值为多少?
答案:
iota 规则
很多资料介绍规则是:
iota 在 const 关键字出现时被重置为 0 ;
const 声明块中每新增一行 iota 值自增 1;
其实规则就一条:
iota 表示 const 声明块的行索引(下标从 0 开始)
const 声明还有个重要特点:
第一个常量必须指定一个表达式,后续的常量如果没有表达式,则继承上面的表达式。
如此,我们再看上面的代码:
解析:
第 0 行的表达式展开即 bit0, mask0 = 1 << 0, 1<<0 - 1 ,所以 bit0 == 1,mask0 == 0;
1 << 0 是把 1 按 2 进制左移 0 位,结果还是 1
第 1 行没有指定表达式继承第一行,即 bit1, mask1 = 1 << 1, 1<<1 - 1 ,所以 bit1 == 2,mask1 == 1;
第 2 行没有定义常量
第 3 行没有指定表达式继承第一行,即 bit3, mask3 = 1 << 3, 1<<3 - 1 ,所以 bit0 == 8,mask0 == 7;
原理
const 块中每一行在 Go 中使用 spec 数据结构描述, spec 声明如下:
这里只看 ValueSpec.Names,此切片中保存了一行中定义的常量,如果一行定义 N 个常量,那么 ValueSpec.Names 切片长度即为 N。
const 块实际上是 spec 类型的切片,用于表示 const 中的多行。
编译期间构造常量时的伪算法如下:
可以看出 iota 实际上是遍历 const 块的索引,每行中即使多次使用 iota,其值也不会递增。
版权声明: 本文为 InfoQ 作者【微客鸟窝】的原创文章。
原文链接:【http://xie.infoq.cn/article/436b943ce287a36fd468b3096】。文章转载请联系作者。
评论