Golang: 常量、枚举,以及魔幻的iota
by 伊布
常量
Golang里的constants就是constants,在编译时创建。常量可以是这几种: numbers, characters (runes), strings or booleans。因为是在编译时处理的,所以常量的值必须是编译器可以搞定的,比如1,”abc”,以及 len(“abc”)。
注意最后这种也是可以的。
和变量不同,常量可以定义了,但是不用。为什么?因为下面要用常量来定义枚举,谁能保证所有枚举就一定会用到呢?
package main
import "fmt"
func main() {
const xxx = 123
fmt.Println(xxx)
const xx2 = "abc"
fmt.Println(xx2)
const xx3 = len("abc")
fmt.Println(xx3)
var x = 123
const xx4 = unsafe.Sizeof(&x)
fmt.Println(xx4)
}
输出
$ go run constants.go
123
abc
3
8
但像 math.Sin(math.Pi/4)
这种就不行了,因为编译器执行的时候没办法去调用runtime的math包。
枚举
golang使用iota来实现枚举。itoa可以定义在表达式里,而且表达式可以隐式重复,因此golang的枚举可以定义的非常花。
举个effective go的例子。
package main
import (
"fmt"
)
type Byte float64
const (
_ = iota
KB Byte = 1 << (10*iota) //iota自动+1,此时值为2,即 1 << (10*2)
MB //表达式自动重复, 1 << (10*iota) 即 1 << (10*3)
GB //...
TB
PB
EB
ZB
YB
)
func (b Byte) String() string {
switch {
case b > YB:
return fmt.Sprintf("%.2fYB", b/YB)
case b > ZB:
return fmt.Sprintf("%.2fZB", b/ZB)
case b > EB:
return fmt.Sprintf("%.2fEB", b/EB)
case b > PB:
return fmt.Sprintf("%.2fPB", b/PB)
case b > TB:
return fmt.Sprintf("%.2fTB", b/TB)
case b > GB:
return fmt.Sprintf("%.2fGB", b/GB)
case b > MB:
return fmt.Sprintf("%.2fMB", b/MB)
case b > KB:
return fmt.Sprintf("%.2fKB", b/KB)
}
return fmt.Sprintf("%.2fB", b)
}
func main() {
var x Byte
x = 1024*1024*1024 * 15
fmt.Println(x)
x = 1024*1024*1024*1024*1024 * 42
fmt.Println(x)
}
iota很魔幻,编译器看到iota会自动给当前作用域下的自动+1,且表达式自动重复。
上面代码输出的结果如下。
$ go run iota.go
15.00GB
42.00PB
没找到iota的实现,应该比较有意思。
为什么是iota这个词呢?据说iota是一个雅典字符,表示求和算法中的迭代器。
iota是有坑的,要小心。
我们注意到,iota能够自动inc,inc的规则是作用域内每行+1。
看这个例子。
package main
import "fmt"
const (
A, B int = iota, iota+1
_, _
C, D
E int = iota+10
)
func main() {
fmt.Println(A, B, C, D, E)
}
输出的是这样的。
$ go run iota2.go
0 1 2 3 13
显然iota是按行递增的,即使每行定义了2个变量。
Ref:
Subscribe via RSS