gopl-zh.github.com/ch3/ch3-06-1.md

2.5 KiB
Raw Blame History

3.6.1. iota 常量生成器

常量聲明可以使用iota常量生成器初始化它用於生成一組以相似規則初始化的常量但是不用每行都寫一遍初始化表達式。在一個const聲明語句中在第一個聲明的常量所在的行iota將會被置爲0然後在每一個有常量聲明的行加一。

下面是來自time包的例子它首先定義了一個Weekday命名類型然後爲一週的每天定義了一個常量從週日0開始。在其它編程語言中這種類型一般被稱爲枚舉類型。

type Weekday int

const (
	Sunday Weekday = iota
	Monday
	Tuesday
	Wednesday
	Thursday
	Friday
	Saturday
)

週一將對應0週一爲1如此等等。

我們也可以在複雜的常量表達式中使用iota下面是來自net包的例子用於給一個無符號整數的最低5bit的每個bit指定一個名字

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
)

隨着iota的遞增每個常量對應表達式1 << iota是連續的2的冪分别對應一個bit位置。使用這些常量可以用於測試、設置或清除對應的bit位的值

gopl.io/ch3/netflag

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"
}

下面是一個更複雜的例子每個常量都是1024的冪

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
)

不過iota常量生成規則也有其局限性。例如它併不能用於産生1000的冪KB、MB等因爲Go語言併沒有計算冪的運算符。

練習 3.13 編寫KB、MB的常量聲明然後擴展到YB。