字面常量
所謂字面常量(literal),是指程序中硬編碼的常量,如:
-12
3.14159265358979323846 // 浮點類型的常量
3.2+12i // 複數類型的常量
true // 布爾類型的常量
"foo" // 字符串常量
在其他語言中,常量通常有特定的類型,比如 -12
在 C 語言中會認爲是一個 int 類型的常量。如果要指定一個值爲 -12
的 long 類型常量,需要寫成 -12l
,這有點違反人們的直觀感覺。Go 語言的字面常量更接近我們自然語言中的常量概念,它是無類型的。只要這個常量在相應類型的值域範圍內,就可以作爲該類型的常量。比如上面的常量 -12
,它可以賦值給 int、uint、int32、int64、float32、float64、complex64、complex128 等類型的變量。
常量定義
通過 const 關鍵字,你可以給字面常量指定一個友好的名字:
const Pi float64 = 3.14159265358979323846
const zero = 0.0 // 無類型浮點常量
const (
size int64 = 1024
eof = -1 // 無類型整型常量
)
const u, v float32 = 0, 3 // u = 0.0, v = 3.0,常量的多重賦值
const a, b, c = 3, 4, "foo"
// a = 3, b = 4, c = "foo", 無類型整型和字符串常量
Go 的常量定義可以限定常量類型,但不是必需的。如果定義常量時沒有指定類型,那麼它與字面常量一樣,是無類型常量。
常量定義的右值也可以是一個在編譯期運算的常量表達式,比如:
const mask = 1 << 3
由於常量的賦值是一個編譯期行爲,所以右值不能出現任何需要運行期才能得出結果的表達式,比如試圖以如下方式定義常量就會導致編譯錯誤:
const Home = os.GetEnv("HOME")
原因很簡單,os.GetEnv() 只有在運行期才能知道返回結果,在編譯期並不能確定,所以無法作爲常量定義的右值。
預定義常量
Go 語言預定義了這些常量:true
、false
和 iota
。
iota 比較特殊,可以被認爲是一個可被編譯器修改的常量,在每一個 const 關鍵字出現時被重置爲 0,然後在下一個 const 出現之前,每出現一次 iota,其所代表的數字會自動增1。
從以下的例子可以基本理解 iota 的用法:
const ( // iota被重設爲0
c0 = iota // c0 == 0
c1 = iota // c1 == 1
c2 = iota // c2 == 2
)
const (
a = 1 << iota // a == 1 (iota在每個const開頭被重設爲0)
b = 1 << iota // b == 2
c = 1 << iota // c == 4
)
const (
u = iota * 42 // u == 0
v float64 = iota * 42 // v == 42.0
w = iota * 42 // w == 84
)
const x = iota // x == 0 (因爲iota又被重設爲0了)
const y = iota // y == 0 (同上)
如果兩個 const 的賦值語句的表達式是一樣的,那麼可以省略後一個賦值表達式。因此,上面的前兩個 const 語句可簡寫爲:
const ( // iota被重設爲0
c0 = iota // c0 == 0
c1 // c1 == 1
c2 // c2 == 2
)
const (
a = 1 <<iota // a == 1 (iota在每個const開頭被重設爲0)
b // b == 2
c // c == 4
)
枚舉
枚舉指一系列相關的常量,比如下面關於一個星期中每天的定義。通過上一節的例子,我們看到可以用在 const 後跟一對圓括號的方式定義一組常量,這種定義法在 Go 語言中通常用於定義枚舉值。Go 語言並不支持衆多其他語言明確支持的 enum 關鍵字。
下面是一個常規的枚舉表示法,其中定義了一系列整型常量:
const (
Sunday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
numberOfDays // 這個常量外部無法訪問
)
同 Go 語言的其他符號(symbol)一樣,以大寫字母開頭的常量在包外可見。以上例子中 numberOfDays 爲包內私有,其他符號則可被其他包訪問。