Go常量
常量的值無法在運行時改變,一旦賦值過後就無法修改,其值只能來源於:
- 字面量
- 其他常量標識符
- 常量表達式
- 結果是常量的類型轉換
- iota
常量只能是基本數據類型,不能是
- 除基本類型以外的其它類型,如結構體,接口,切片,數組等
- 函數的返回值
常量的值無法被修改,否則無法通過編譯
初始化
常量的聲明需要用到const關鍵字,常量在聲明時就必須初始化一個值,並且常量的類型可以省略,例如
const name string = "Jack" // 字面量
const msg = "hello world" // 字面量
const num = 1 // 字面量
const numExpression = (1+2+3) / 2 % 100 + num // 常量表達式如果僅僅只是聲明而不指定值,將會無法通過編譯
const name string編譯器報錯
missing init expr for name批量聲明常量可以用()括起來以提升可讀性,可以存在多個()達到分組的效果。
const (
Count = 1
Name = "Jack"
)
const (
Size = 16
Len = 25
)在同一個常量分組中,在已經賦值的常量後面的常量可以不用賦值,其值默認就是前一個的值,比如
const (
A = 1
B // 1
C // 1
D // 1
E // 1
)iota
iota是一個內置的常量標識符,通常用於表示一個常量聲明中的無類型整數序數,一般都是在括號中使用。
const iota = 0看幾個使用案例
const (
Num = iota // 0
Num1 // 1
Num2 // 2
Num3 // 3
Num4 // 4
)也可以這麼寫
const (
Num = iota*2 // 0
Num1 // 2
Num2 // 4
Num3 // 6
Num4 // 8
)還可以
const (
Num = iota << 2*3 + 1 // 1
Num1 // 13
Num2 // 25
Num3 = iota // 3
Num4 // 4
)通過上面幾個例子可以發現,iota是遞增的,第一個常量使用iota值的表達式,根據序號值的變化會自動的賦值給後續的常量,直到用新的const重置,這個序號其實就是代碼的相對行號,是相對於當前分組的起始行號,看下面的例子
const (
Num = iota<<2*3 + 1 // 1 第一行
Num2 = iota<<2*3 + 1 // 13 第二行
_ // 25 第三行
Num3 //37 第四行
Num4 = iota // 4 第五行
_ // 5 第六行
Num5 // 6 第七行
)例子中使用了匿名標識符_佔了一行的位置,可以看到iota的值本質上就是iota所在行相對於當前const分組的第一行的差值。而不同的const分組則相互不會影響。
枚舉
Go 語言沒有為枚舉單獨設計一個數據類型,不像其它語言通常會有一個enum來表示。一般在 Go 中,都是通過自定義類型 + const + iota 來實現枚舉,下面是一個簡單的例子
type Season uint8
const (
Spring Season = iota
Summer
Autumn
Winter
)這些枚舉實際上就是數字,Go 也不支持直接將其轉換為字符串,但我們可以通過給自定義類型添加方法來返回其字符串表現形式,實現Stringer接口即可。
func (s Season) String() string {
switch s {
case Spring:
return "spring"
case Summer:
return "summer"
case Autumn:
return "autumn"
case Winter:
return "winter"
}
return ""
}這樣一來就是一個簡單的枚舉實現了。你也可以通過官方工具Stringer來自動生成枚舉。
不過它有以下缺點:
類型不安全,因為
Season是自定義類型,可以通過強制類型轉換將其他數字也轉換成該類型goSeason(6)繁瑣,字符串表現形式需要自己實現
表達能力弱,因為
const僅支持基本數據類型,所以這些枚舉值也只能用字符串和數字來進行表示
為什麼不在語言層面支持枚舉是筆者非常不能理解的一件事,我認為這絕對是利大於弊的。
