其实iota这个常量应该是编译器的常量,iota是一个编译器在编译过程中动态赋值。
iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。
下面代码,从golang标准库的mutex拿出来的,是一个互斥锁的结构体(关于Mutex不细说这里),里面定义有这样的常量。
例子1:
package main
import (
"fmt"
)
const (
mutexLocked = 1 << iota // mutex is locked
mutexWoken
mutexStarving
mutexWaiterShift = iota
)
func main() {
fmt.Printf("mutexLocked : %T = %v\n", mutexLocked, mutexLocked)
fmt.Printf("mutexWoken : %T = %v\n", mutexWoken, mutexWoken)
fmt.Printf("mutexStarving : %T = %v\n", mutexStarving, mutexStarving)
fmt.Printf("mutexWaiterShift : %T = %v\n", mutexWaiterShift, mutexWaiterShift)
}
让我不解的是,mutexLocked为1是可以理解的。数字1往左移动0位,也就是没有移动,数值保持不变。为什么mutexWoken=2?mutexStarving =4?。
接着我们再来看一个例子2:
package main
import "fmt"
func main() {
const (
a = iota //0
b //1
c //2
d = "ha" //独立值,iota += 1
e //"ha" iota += 1
f = 100 //iota +=1
g //100 iota +=1
h = iota //7,恢复计数
i //8
)
fmt.Println(a, b, c, d, e, f, g, h, i)
}
d和e值相同,f和g值相同。从上面这个例子,可以得到这样一个结论。
在const声明中,变量缺省值时,默认使用上一行的常量赋值方式。e直接使用上一行的d值(ha)。
现在返回去看例子1.
mutexLocked = 1 << iota // mutex is locked
mutexWoken
mutexStarving
mutexWaiterShift = iota
mutexLocked=1<<iota
根据我们上面得到结论,
mutexWoken和mutexStarving同样使用1<<iota式子。特殊在于iota每一行的值自动iota++,mutexWoken=1<<1等于1*21=2,mutexStarving=1<<2等于1*22=4。mutexWaiterShift = iota,此时iota正好为3.