2015-12-16 06:03:43 +00:00
|
|
|
|
### 3.6.1. iota 常量生成器
|
|
|
|
|
|
2016-02-15 03:06:34 +00:00
|
|
|
|
常量声明可以使用iota常量生成器初始化,它用于生成一组以相似规则初始化的常量,但是不用每行都写一遍初始化表达式。在一个const声明语句中,在第一个声明的常量所在的行,iota将会被置为0,然后在每一个有常量声明的行加一。
|
2015-12-21 03:10:24 +00:00
|
|
|
|
|
2016-02-15 03:06:34 +00:00
|
|
|
|
下面是来自time包的例子,它首先定义了一个Weekday命名类型,然后为一周的每天定义了一个常量,从周日0开始。在其它编程语言中,这种类型一般被称为枚举类型。
|
2015-12-21 03:10:24 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
|
|
|
|
type Weekday int
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
Sunday Weekday = iota
|
|
|
|
|
Monday
|
|
|
|
|
Tuesday
|
|
|
|
|
Wednesday
|
|
|
|
|
Thursday
|
|
|
|
|
Friday
|
|
|
|
|
Saturday
|
|
|
|
|
)
|
|
|
|
|
```
|
|
|
|
|
|
2016-02-19 04:15:27 +00:00
|
|
|
|
周日将对应0,周一为1,如此等等。
|
2015-12-21 03:10:24 +00:00
|
|
|
|
|
2016-02-15 03:06:34 +00:00
|
|
|
|
我们也可以在复杂的常量表达式中使用iota,下面是来自net包的例子,用于给一个无符号整数的最低5bit的每个bit指定一个名字:
|
2015-12-21 03:10:24 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
|
|
|
|
type Flags uint
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
FlagUp Flags = 1 << iota // is up
|
|
|
|
|
FlagBroadcast // supports broadcast access capability
|
|
|
|
|
FlagLoopback // is a loopback interface
|
|
|
|
|
FlagPointToPoint // belongs to a point-to-point link
|
|
|
|
|
FlagMulticast // supports multicast access capability
|
|
|
|
|
)
|
|
|
|
|
```
|
|
|
|
|
|
2016-02-15 03:06:34 +00:00
|
|
|
|
随着iota的递增,每个常量对应表达式1 << iota,是连续的2的幂,分别对应一个bit位置。使用这些常量可以用于测试、设置或清除对应的bit位的值:
|
2015-12-21 03:10:24 +00:00
|
|
|
|
|
2016-01-20 15:25:13 +00:00
|
|
|
|
<u><i>gopl.io/ch3/netflag</i></u>
|
2015-12-21 03:10:24 +00:00
|
|
|
|
```Go
|
|
|
|
|
func IsUp(v Flags) bool { return v&FlagUp == FlagUp }
|
|
|
|
|
func TurnDown(v *Flags) { *v &^= FlagUp }
|
|
|
|
|
func SetBroadcast(v *Flags) { *v |= FlagBroadcast }
|
|
|
|
|
func IsCast(v Flags) bool { return v&(FlagBroadcast|FlagMulticast) != 0 }
|
|
|
|
|
|
|
|
|
|
unc main() {
|
|
|
|
|
var v Flags = FlagMulticast | FlagUp
|
|
|
|
|
fmt.Printf("%b %t\n", v, IsUp(v)) // "10001 true"
|
|
|
|
|
TurnDown(&v)
|
|
|
|
|
fmt.Printf("%b %t\n", v, IsUp(v)) // "10000 false"
|
|
|
|
|
SetBroadcast(&v)
|
|
|
|
|
fmt.Printf("%b %t\n", v, IsUp(v)) // "10010 false"
|
|
|
|
|
fmt.Printf("%b %t\n", v, IsCast(v)) // "10010 true"
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2016-02-15 03:06:34 +00:00
|
|
|
|
下面是一个更复杂的例子,每个常量都是1024的幂:
|
2015-12-21 03:10:24 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
|
|
|
|
const (
|
|
|
|
|
_ = 1 << (10 * iota)
|
|
|
|
|
KiB // 1024
|
|
|
|
|
MiB // 1048576
|
|
|
|
|
GiB // 1073741824
|
|
|
|
|
TiB // 1099511627776 (exceeds 1 << 32)
|
|
|
|
|
PiB // 1125899906842624
|
|
|
|
|
EiB // 1152921504606846976
|
|
|
|
|
ZiB // 1180591620717411303424 (exceeds 1 << 64)
|
|
|
|
|
YiB // 1208925819614629174706176
|
|
|
|
|
)
|
|
|
|
|
```
|
|
|
|
|
|
2016-02-15 03:06:34 +00:00
|
|
|
|
不过iota常量生成规则也有其局限性。例如,它并不能用于产生1000的幂(KB、MB等),因为Go语言并没有计算幂的运算符。
|
2015-12-21 03:10:24 +00:00
|
|
|
|
|
2016-02-15 03:06:34 +00:00
|
|
|
|
**练习 3.13:** 编写KB、MB的常量声明,然后扩展到YB。
|