Golang iota常量计算原理

iota,一个很奇怪的英文单词,一直想弄清楚其中文含义,但经过查证,它并不是英文缩写,而是一个完整的希腊单词,没有具体意思,常做为数学符号使用。

1. 常见用法

iota主要用于常量自增,如下面一个很常见的例子,当iota赋值给常数A后,第一个常数A值为0,后面的常数会自动加1:

const (
    A = iota     // 0
    B            // 1
    C            // 2
)

还可以给常量声明一个类型,如下:

type Alpa int

const (
    A Alpa = iota     // 0
    B                 // 1
    C                 // 2
)

有时想定义的常量值不连续或保留某些值,可以使用_跳过。如下:

const (
    A = iota     // 0
    _
    B            // 2
    C            // 3
)

可以看到B值为2,跳过了1。

2. 非常见用法

初识iota时,一直以为iota赋值的第一个常量为0,往后逐个自增,但后来见到的一些奇怪用法,让我知道iota并没有那么简单。下面展示了一些非常见用法:

示例1:

const (
    A = 1  
    B = iota
    C    
)

B,C的值分别是多少?

示例2:

const (
    A = 1 << iota
    B 
    C    
)

B,C的值分别是多少?

示例3:

const (
	A, B = iota+1, iota+2  
	C, D                 
 	E, F                 
)

A,B,C,D,E,F的值分别是多少?

示例4:

const (
    A = iota
    B = 3
    C    
    D
)

C,D的值分别是多少?

示列5:

const (
	A = -(iota)
	B
	C
)

B,C的值分别是多少?

答案:
示例1:B=1,C=2
示例2:B=2,C=4
示例3:A=1,B=2,C=2,D=3,E=3,F=4
示例4:C=3,D=3
示例5:B=-1,C=-2

对照上面答案,如果这些你都能做对,说明你完全了解了iota求值方法,后面的不需要看了,如果不是很确定,有点模糊,或已经崩溃,那么下面的会对你非常有帮助。

3. iota计算规则

为了更好了解iota计算规则,我们先要知道一些概念。

3.1 iota 作用范围

iota的作用范围仅限于自已所在的const声明,多个const都使用iota会不会互相影响。如下示例:

const (
    A1 = iota     // 0
    A2            // 1
    A3            // 2
)

const (
    B0 = iota     // 0
    B1            // 1
    c2            // 2
)

两个const里面的常量并没有互相影响。

3.2 常量编号

在一个const下,每一个的常量都有一个编号,但这个编号并不是常量的顺序号,而是const内部的行号,行号从0开始。如何理解,请看下面示例:

const (
	A = iota        // 0
    _               // 1
    B               // 2
    C               // 3
)

常量A在const内部行号为0,因此编号也为0;常量B在const内部行号为2,因此编号也为2。

再举个例子:

const (
	A, B = iota+1, iota+2  // A行号=0,B行号=0
	C, D                   // C行号=1,D行号=1
 	E, F                   // E行号=2,F行号=2
)

常量A, B在const内部行号为0,因此编号都为0;常量C, D在const内部行号为1,因此编号都为1。可以看出常量编号并非常量的顺序号。

谨记编号是常量所在const内部的行号。

3.3 常量表达式

等号右边的是表达式

常量名 = 表达式

const (
	A = iota     
    B = 1 << iota
    C = -(iota)            
    D = iota*10            
)

常量A的表达式为:iota
常量B的表达式为:1 << iota
常量C的表达式为:-(iota)
常量D的表达式为:iota*10

3.4 表达式惯性

如果常量没有表达式,会继承它上面常量的表达式。第一个常量必须有表达式,否则会编译失败。示例如下:

const (
	A = iota     
	B         
    C = 3        
    D            
    E = iota << 1
    F
    G
)

如果把上面所有常量表达式补齐,会变成:

const (
	A = iota     
	B = iota     
    C = 3        
    D = 3           
    E = iota << 1
    F = iota << 1
)

常量B会继承常量A的表达式;常量D会继承常量C的表达式;常量F会继承常量E的表达式;常量G会继承常量F的表达式,由于F继承了E的,那相当于G也继承了E的表达式。

第一个常量必须有表达式,如果没有会报错,因为它没有可以继承的,如下:

	A 
	B = iota   

报错:missing constant value

对于一行多个常量,也遵循表达式惯性规律:C继承A, E继承C,D继承B, F继承D。

const (
	A, B = iota+1, iota+2  
	C, D                   
 	E, F        
)

常量表达式补齐,会变成:

const (
	A, B = iota+1, iota+2  
	C, D = iota+1, iota+2                    
 	E, F = iota+1, iota+2                    
)

A,B都要有表达式,任何一个没有都会报错。

如果有用到表达式惯性规则,则每一行必须有相同的常量数,否则会报错,如下:

const (
	A, B, C = iota+1, iota+2, iota+3
	D, E                 
)

报错:extra expression in const declaration

但如果没有用到表达式惯性规则,则不会有问题,如下:

const (
	A, B, C = iota+1, iota+2, iota+3
	D, E = iota+3, iota+3            
)

编译成功,没问题。

3.5 常量值计算公式

上面对iota的一些基本概念介绍清楚了,下面进入正题–iota的值到底是怎么算的?其实很简单,把表达式中的iota替换成常量编号进行计算即可。

如上面介绍表达式例子:

const (
	A = iota     
    B = 1 << iota
    C = -(iota)            
    D = iota*10            
)

常量A的表达式为:iota,编号为0,将编号替换表达式的iota,表达式为0,最后A的值为0。
常量B的表达式为:1 << iota,编号为1,将编号替换表达式的iota,表达式为1<<1,B的值为2。
常量C的表达式为:-(iota),编号为2,将编号替换表达式的iota,表达式为-(2),B的值为-2。
常量D的表达式为:iota*10,编号为3,将编号替换表达式的iota,表达式为```3*10``,B的值为30。

通过程序验证结果与上面完全符号。
运行结果
再验证一个:

const (
	A, B = iota+1, iota+2  
	C, D                         
)

常量A的表达式为:iota+1,A的编号为0,将编号替换表达式的iota,表达式为0+1,A的值为1。
常量B的表达式为:iota+2,B的编号为0,将编号替换表达式的iota,表达式为0+2,B的值为2。
常量C的表达式为:iota+1,C的编号为1,将编号替换表达式的iota,表达式为1+1,C的值为2。
常量D的表达式为:iota+2,D的编号为1,将编号替换表达式的iota,表达式为1+2,D的值为3。

程序验证:
在这里插入图片描述

了解了iota计算规则后,再也不会有常量值弄不清的问题了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值