Go 經(jīng)典入門系列 5:常量
這是我們 Golang 系列教程的第五篇。
定義
在 Go 語言中,術(shù)語"常量"用于表示固定的值。比如 5 、-89、 I love Go、67.89 等等。
看看下面的代碼:
var?a?int?=?50
var?b?string?=?"I?love?Go"
在上面的代碼中,變量 a 和 b 分別被賦值為常量 50 和 I love GO。關(guān)鍵字 const 被用于表示常量,比如 50 和 I love Go。即使在上面的代碼中我們沒有明確的使用關(guān)鍵字 const,但是在 Go 的內(nèi)部,它們是常量。
顧名思義,常量不能再重新賦值為其他的值。因此下面的程序?qū)⒉荒苷9ぷ鳎鼘⒊霈F(xiàn)一個編譯錯誤: cannot assign to a.。
package?main
func?main()?{
????const?a?=?55?//?允許
????a?=?89???????//?不允許重新賦值
}
在線運(yùn)行程序[1]
常量的值會在編譯的時候確定。因為函數(shù)調(diào)用發(fā)生在運(yùn)行時,所以不能將函數(shù)的返回值賦值給常量。
package?main
import?(
????"fmt"
????"math"
)
func?main()?{
????fmt.Println("Hello,?playground")
????var?a?=?math.Sqrt(4)???//?允許
????const?b?=?math.Sqrt(4)?//?不允許
}
在線運(yùn)行程序[2]
在上面的程序中,因為 a 是變量,因此我們可以將函數(shù) math.Sqrt(4) 的返回值賦值給它(我們將在單獨(dú)的地方詳細(xì)討論函數(shù))。
b 是一個常量,它的值需要在編譯的時候就確定。函數(shù) math.Sqrt(4) 只會在運(yùn)行的時候計算,因此 const b = math.Sqrt(4) 將會拋出錯誤 error main.go:11: const initializer math.Sqrt(4) is not a constant)
字符串常量
雙引號中的任何值都是 Go 中的字符串常量。例如像 Hello World 或 Sam 等字符串在 Go 中都是常量。
什么類型的字符串屬于常量?答案是他們是無類型的。
像 Hello World 這樣的字符串常量沒有任何類型。
const?hello?=?"Hello?World"
上面的例子,我們把 Hello World 分配給常量 hello。現(xiàn)在常量 hello 有類型嗎?答案是沒有。常量仍然沒有類型。
Go 是一門強(qiáng)類型語言,所有的變量必須有明確的類型。那么, 下面的程序是如何將無類型的常量 Sam 賦值給變量 name 的呢?
package?main
import?(
????"fmt"
)
func?main()?{
????var?name?=?"Sam"
????fmt.Printf("type?%T?value?%v",?name,?name)
}
在線運(yùn)行程序[3]
答案是無類型的常量有一個與它們相關(guān)聯(lián)的默認(rèn)類型,并且當(dāng)且僅當(dāng)一行代碼需要時才提供它。在聲明中 var name = "Sam" , name 需要一個類型,它從字符串常量 Sam 的默認(rèn)類型中獲取。
有沒有辦法創(chuàng)建一個帶類型的常量?答案是可以的。以下代碼創(chuàng)建一個有類型常量。
const?typedhello?string?=?"Hello?World"
上面代碼中, typedhello 就是一個 string 類型的常量。
Go 是一個強(qiáng)類型的語言,在分配過程中混合類型是不允許的。讓我們通過以下程序看看這句話是什么意思。
package?main
func?main()?{
????????var?defaultName?=?"Sam"?//?允許
????????type?myString?string
????????var?customName?myString?=?"Sam"?//?允許
????????customName?=?defaultName?//?不允許
}
在線運(yùn)行程序[4]
在上面的代碼中,我們首先創(chuàng)建一個變量 defaultName 并分配一個常量 Sam 。常量 Sam 的默認(rèn)類型是 string ,所以在賦值后 defaultName 是 string 類型的。
下一行,我們將創(chuàng)建一個新類型 myString,它是 string 的別名。
然后我們創(chuàng)建一個 myString 的變量 customName 并且給他賦值一個常量 Sam 。因為常量 Sam 是無類型的,它可以分配給任何字符串變量。因此這個賦值是允許的,customName 的類型是 myString。
現(xiàn)在,我們有一個類型為 string 的變量 defaultName 和另一個類型為 myString 的變量 customName。即使我們知道這個 myString 是 string 類型的別名。Go 的類型策略不允許將一種類型的變量賦值給另一種類型的變量。因此將 defaultName 賦值給 customName 是不允許的,編譯器會拋出一個錯誤 main.go:7:20: cannot use defaultName (type string) as type myString in assignmen。
布爾常量
布爾常量和字符串常量沒有什么不同。他們是兩個無類型的常量 true 和 false。字符串常量的規(guī)則適用于布爾常量,所以在這里我們不再重復(fù)。以下是解釋布爾常量的簡單程序。
package?main
func?main()?{
????const?trueConst?=?true
????type?myBool?bool
????var?defaultBool?=?trueConst?//?允許
????var?customBool?myBool?=?trueConst?//?允許
????defaultBool?=?customBool?//?不允許
}
在線運(yùn)行程序[5]
上面的程序是自我解釋的。
數(shù)字常量
數(shù)字常量包含整數(shù)、浮點數(shù)和復(fù)數(shù)的常量。數(shù)字常量中有一些微妙之處。
讓我們看一些例子來說清楚。
package?main
import?(
????"fmt"
)
func?main()?{
????const?a?=?5
????var?intVar?int?=?a
????var?int32Var?int32?=?a
????var?float64Var?float64?=?a
????var?complex64Var?complex64?=?a
????fmt.Println("intVar",intVar,?"\nint32Var",?int32Var,?"\nfloat64Var",?float64Var,?"\ncomplex64Var",complex64Var)
}
在線運(yùn)行程序[6]
上面的程序,常量 a 是沒有類型的,它的值是 5 。您可能想知道 a 的默認(rèn)類型是什么,如果它確實有一個的話, 那么我們?nèi)绾螌⑺峙浣o不同類型的變量。答案在于 a 的語法。下面的程序?qū)⑹故虑楦忧逦?/p>
package?main
import?(
????"fmt"
)
func?main()?{
????var?i?=?5
????var?f?=?5.6
????var?c?=?5?+?6i
????fmt.Printf("i's?type?%T,?f's?type?%T,?c's?type?%T",?i,?f,?c)
}
在線運(yùn)行程序[7]
在上面的程序中,每個變量的類型由數(shù)字常量的語法決定。5 在語法中是整數(shù), 5.6 是浮點數(shù),5+6i 的語法是復(fù)數(shù)。當(dāng)我們運(yùn)行上面的程序,它會打印出 i's type int, f's type float64, c's type complex128。
現(xiàn)在我希望下面的程序能夠正確的工作。
package?main
import?(
????"fmt"
)
func?main()?{
????const?a?=?5
????var?intVar?int?=?a
????var?int32Var?int32?=?a
????var?float64Var?float64?=?a
????var?complex64Var?complex64?=?a
????fmt.Println("intVar",intVar,?"\nint32Var",?int32Var,?"\nfloat64Var",?float64Var,?"\ncomplex64Var",complex64Var)
}
在線運(yùn)行程序[8]
在這個程序中, a 的值是 5 ,a 的語法是通用的(它可以代表一個浮點數(shù)、整數(shù)甚至是一個沒有虛部的復(fù)數(shù)),因此可以將其分配給任何兼容的類型。這些常量的默認(rèn)類型可以被認(rèn)為是根據(jù)上下文在運(yùn)行中生成的。var intVar int = a 要求 a 是 int,所以它變成一個 int 常量。var complex64Var complex64 = a 要求 a 是 complex64,因此它變成一個復(fù)數(shù)類型。很簡單的:)。
數(shù)字表達(dá)式
數(shù)字常量可以在表達(dá)式中自由混合和匹配,只有當(dāng)它們被分配給變量或者在需要類型的代碼中的任何地方使用時,才需要類型。
package?main
import?(
????"fmt"
)
func?main()?{
????var?a?=?5.9/8
????fmt.Printf("a's?type?%T?value?%v",a,?a)
}
在線運(yùn)行程序[9]
在上面的程序中, 5.9 在語法中是浮點型,8 是整型,5.9/8 是允許的,因為兩個都是數(shù)字常量。除法的結(jié)果是 0.7375 是一個浮點型,所以 a 的類型是浮點型。這個程序的輸出結(jié)果是: a's type float64 value 0.7375。
下一教程 - 函數(shù)[10]
via: https://golangbot.com/constants/
作者:Nick Coghlan[11]譯者:guoxiaopang[12]校對:polaris1119[13]
本文由 GCTT[14] 原創(chuàng)編譯,Go 中文網(wǎng)[15] 榮譽(yù)推出
參考資料
在線運(yùn)行程序: https://play.golang.org/p/b2J8_UQobb
[2]在線運(yùn)行程序: https://play.golang.org/p/dCON1LzCTw
[3]在線運(yùn)行程序: https://play.golang.org/p/xhYV4we_Jz
[4]在線運(yùn)行程序: https://play.golang.org/p/1Q-vudNn_9
[5]在線運(yùn)行程序: https://play.golang.org/p/h9yzC6RxOR
[6]在線運(yùn)行程序: https://play.golang.org/p/a8sxVNdU8M
[7]在線運(yùn)行程序: https://play.golang.org/p/kJq69Vpqit
[8]在線運(yùn)行程序: https://play.golang.org/p/_zu0iK-Hyj
[9]在線運(yùn)行程序: https://play.golang.org/p/-8i-iX-jIG
[10]函數(shù): https://studygolang.com/articles/11892
[11]Nick Coghlan: https://golangbot.com/about/
[12]guoxiaopang: https://github.com/guoxiaopang
[13]polaris1119: https://github.com/polaris1119
[14]GCTT: https://github.com/studygolang/GCTT
[15]Go 中文網(wǎng): https://studygolang.com/
推薦閱讀
