2015-12-09 07:45:11 +00:00
|
|
|
|
## 3.6. 常量
|
|
|
|
|
|
2015-12-28 03:14:18 +00:00
|
|
|
|
常量表達式的值在編譯期計算,而不是在運行期。每種常量的潛在類型都是基礎類型:boolean、string或數字。
|
2015-12-21 02:49:43 +00:00
|
|
|
|
|
2015-12-28 03:14:18 +00:00
|
|
|
|
一個常量的聲明語句定義了常量的名字,和變量的聲明語法類似,常量的值不可脩改,這樣可以防止在運行期被意外或惡意的脩改。例如,常量比變量更適合用於表達像π之類的數學常數,因爲它們的值不會發生變化:
|
2015-12-21 02:49:43 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
|
|
|
|
const pi = 3.14159 // approximately; math.Pi is a better approximation
|
|
|
|
|
```
|
|
|
|
|
|
2015-12-28 03:14:18 +00:00
|
|
|
|
和變量聲明一樣,可以批量聲明多個常量;這比較適合聲明一組相關的常量:
|
2015-12-21 02:49:43 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
|
|
|
|
const (
|
|
|
|
|
e = 2.71828182845904523536028747135266249775724709369995957496696763
|
|
|
|
|
pi = 3.14159265358979323846264338327950288419716939937510582097494459
|
|
|
|
|
)
|
|
|
|
|
```
|
|
|
|
|
|
2015-12-28 03:14:18 +00:00
|
|
|
|
所有常量的運算都可以在編譯期完成,這樣可以減少運行時的工作,也方便其他編譯優化。當操作數是常量時,一些運行時的錯誤也可以在編譯時被發現,例如整數除零、字符串索引越界、任何導致無效浮點數的操作等。
|
2015-12-21 02:49:43 +00:00
|
|
|
|
|
2015-12-28 03:14:18 +00:00
|
|
|
|
常量間的所有算術運算、邏輯運算和比較運算的結果也是常量,對常量的類型轉換操作或以下函數調用都是返迴常量結果:len、cap、real、imag、complex和unsafe.Sizeof(§13.1)。
|
2015-12-21 02:49:43 +00:00
|
|
|
|
|
2015-12-28 03:14:18 +00:00
|
|
|
|
因爲它們的值是在編譯期就確定的,因此常量可以是構成類型的一部分,例如用於指定數組類型的長度:
|
2015-12-21 02:49:43 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
|
|
|
|
const IPv4Len = 4
|
|
|
|
|
|
|
|
|
|
// parseIPv4 parses an IPv4 address (d.d.d.d).
|
|
|
|
|
func parseIPv4(s string) IP {
|
|
|
|
|
var p [IPv4Len]byte
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2015-12-28 03:14:18 +00:00
|
|
|
|
一個常量的聲明也可以包含一個類型和一個值,但是如果沒有顯式指明類型,那麽將從右邊的表達式推斷類型。在下面的代碼中,time.Duration是一個命名類型,底層類型是int64,time.Minute是對應類型的常量。下面聲明的兩個常量都是time.Duration類型,可以通過%T參數打印類型信息:
|
2015-12-21 02:49:43 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
|
|
|
|
const noDelay time.Duration = 0
|
|
|
|
|
const timeout = 5 * time.Minute
|
|
|
|
|
fmt.Printf("%T %[1]v\n", noDelay) // "time.Duration 0"
|
2016-01-07 07:02:42 +00:00
|
|
|
|
fmt.Printf("%T %[1]v\n", timeout) // "time.Duration 5m0s"
|
2015-12-21 02:49:43 +00:00
|
|
|
|
fmt.Printf("%T %[1]v\n", time.Minute) // "time.Duration 1m0s"
|
|
|
|
|
```
|
|
|
|
|
|
2015-12-28 03:14:18 +00:00
|
|
|
|
如果是批量聲明的常量,除了第一個外其它的常量右邊的初始化表達式都可以省略,如果省略初始化表達式則表示使用前面常量的初始化表達式寫法,對應的常量類型也一樣的。例如:
|
2015-12-21 02:49:43 +00:00
|
|
|
|
|
|
|
|
|
```Go
|
|
|
|
|
const (
|
|
|
|
|
a = 1
|
|
|
|
|
b
|
|
|
|
|
c = 2
|
|
|
|
|
d
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
fmt.Println(a, b, c, d) // "1 1 2 2"
|
|
|
|
|
```
|
|
|
|
|
|
2015-12-28 03:14:18 +00:00
|
|
|
|
如果隻是簡單地複製右邊的常量表達式,其實併沒有太實用的價值。但是它可以帶來其它的特性,那就是iota常量生成器語法。
|
2015-12-16 06:03:43 +00:00
|
|
|
|
|
|
|
|
|
{% include "./ch3-06-1.md" %}
|
|
|
|
|
|
|
|
|
|
{% include "./ch3-06-2.md" %}
|
|
|
|
|
|
2015-12-21 02:49:43 +00:00
|
|
|
|
|
|
|
|
|
|