Go語言中的常量使用關鍵字 const 定義,用于存儲不會改變的資料,常量是在編譯時被建立的,即使定義在函數内部也是如此,并且隻能是布爾型、數字型(整數型、浮點型和複數)和字元串型。由于編譯時的限制,定義常量的表達式必須為能被編譯器求值的常量表達式。
常量的定義格式和變量的聲明文法類似:const name [type]=value,例如:
const pi=3.14159 // 相當于 math.Pi 的近似值
在Go語言中,你可以省略類型說明符 [type],因為編譯器可以根據變量的值來推斷其類型。
顯式類型定義: const b string="abc"
隐式類型定義: const b="abc"
常量的值必須是能夠在編譯時就能夠确定的,可以在其指派表達式中涉及計算過程,但是所有用于計算的值必須在編譯期間就能獲得。
正确的做法:const c1=2/3
錯誤的做法:const c2=getNumber() // 引發建構錯誤: getNumber() 用做值
和變量聲明一樣,可以批量聲明多個常量:
const (
e=2.7182818
pi=3.1415926
)
所有常量的運算都可以在編譯期完成,這樣不僅可以減少運作時的工作,也友善其他代碼的編譯優化,當操作數是常量時,一些運作時的錯誤也可以在編譯時被發現,例如整數除零、字元串索引越界、任何導緻無效浮點數的操作等。
常量間的所有算術運算、邏輯運算和比較運算的結果也是常量,對常量的類型轉換操作或以下函數調用都是傳回常量結果:len、cap、real、imag、complex 和 unsafe.Sizeof。
因為它們的值是在編譯期就确定的,是以常量可以是構成類型的一部分,例如用于指定數組類型的長度:
const IPv4Len=4
// parseIPv4 解析一個 IPv4 位址 (d.d.d.d).
func parseIPv4(s string) IP {
var p [IPv4Len]byte
// ...
}
一個常量的聲明也可以包含一個類型和一個值,但是如果沒有顯式指明類型,那麼将從右邊的表達式推斷類型。在下面的代碼中,time.Duration 是一個命名類型,底層類型是 int64,time.Minute 是對應類型的常量。下面聲明的兩個常量都是 time.Duration 類型,可以通過 %T 參數列印類型資訊:
const noDelay time.Duration=0
const timeout=5 * time.Minute
fmt.Printf("%T %[1]v
", noDelay) // "time.Duration 0"
fmt.Printf("%T %[1]v
", timeout) // "time.Duration 5m0s"
fmt.Printf("%T %[1]v
", time.Minute) // "time.Duration 1m0s"
如果是批量聲明的常量,除了第一個外其它的常量右邊的初始化表達式都可以省略,如果省略初始化表達式則表示使用前面常量的初始化表達式,對應的常量類型也是一樣的。例如:
const (
a=1
b
c=2
d
)
fmt.Println(a, b, c, d) // "1 1 2 2"
如果隻是簡單地複制右邊的常量表達式,其實并沒有太實用的價值。但是它可以帶來其它的特性,那就是 iota 常量生成器文法。
iota 常量生成器
常量聲明可以使用 iota 常量生成器初始化,它用于生成一組以相似規則初始化的常量,但是不用每行都寫一遍初始化表達式。在一個 const 聲明語句中,在第一個聲明的常量所在的行,iota 将會被置為 0,然後在每一個有常量聲明的行加一。
【示例 1】首先定義一個 Weekday 命名類型,然後為一周的每天定義了一個常量,從周日 0 開始。在其它程式設計語言中,這種類型一般被稱為枚舉類型。
type Weekday int
const (
Sunday Weekday=iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
)
周日将對應 0,周一為 1,以此類推。
無類型常量
Go語言的常量有個不同尋常之處。雖然一個常量可以有任意一個确定的基礎類型,例如 int 或 float64,或者是類似 time.Duration 這樣的基礎類型,但是許多常量并沒有一個明确的基礎類型。
編譯器為這些沒有明确的基礎類型的數字常量提供比基礎類型更高精度的算術運算,可以認為至少有 256bit 的運算精度。這裡有六種未明确類型的常量類型,分别是無類型的布爾型、無類型的整數、無類型的字元、無類型的浮點數、無類型的複數、無類型的字元串。
通過延遲明确常量的具體類型,不僅可以提供更高的運算精度,而且可以直接用于更多的表達式而不需要顯式的類型轉換。
【示例 2】math.Pi 無類型的浮點數常量,可以直接用于任意需要浮點數或複數的地方:
var x float32=math.Pi
var y float64=math.Pi
var z complex128=math.Pi
如果 math.Pi 被确定為特定類型,比如 float64,那麼結果精度可能會不一樣,同時對于需要 float32 或 complex128 類型值的地方則需要一個明确的強制類型轉換:
const Pi64 float64=math.Pi
var x float32=float32(Pi64)
var y float64=Pi64