背景
Honeycomb的首席開釋出道者Jessica在Twitter上發了一條狀態:
fmt.Println("What is truth?", true)
can output:
What is truth? false
意思是下面程式碼的執行結果可能是What is truth? false
fmt.Println("What is truth?", true)
大家可以先想想什麼情況下會出現這樣的結果。
解析
我們來看下面這段程式碼:
// identifier.go
package main
import "fmt"
func main() {
true := false
fmt.Println(true)
}
大家覺得這段程式碼是會編譯報錯呢,還是正常執行?
實際執行結果是列印false
,並不會編譯報錯。
因此本文開頭的程式碼fmt.Println("What is truth?", true)
是可能列印What is truth? false
的。
有的同學可能好奇了?為什麼會這樣呢?true
不是Go語言的關鍵字麼,為什麼還可以定義識別符號為true
的變數?
答案是:true
並不是Go語言的關鍵字,Go語言目前只有25個關鍵字,如下所示:
break default func interface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var
這些關鍵字是不可以用來作為Go語言的識別符號的。true
是預宣告識別符號,是可以作為Go語言的識別符號的,官方說明如下:
Predeclared identifiers
The following identifiers are implicitly declared in the universe block:
Types: bool byte complex64 complex128 error float32 float64 int int8 int16 int32 int64 rune string uint uint8 uint16 uint32 uint64 uintptr Constants: true false iota Zero value: nil Functions: append cap close complex copy delete imag len make new panic print println real recover
因此true := false
這樣的程式碼在Go語言是可以正常編譯通過的,並且go vet
也不會檢測出任何潛在錯誤。
不僅僅是true
,預宣告識別符號裡的所有識別符號都可以用來作為全域性變數和區域性變數的識別符號,比如下面的程式碼:
// identifier2.go
package main
import "fmt"
var nil = 100
var false = true
func main() {
true := false
fmt.Println(true, false, nil)
}
大家可以想想輸出結果是什麼?
- A:
true false nil
- B:
true false 100
- C:
true true 100
- D:
false true 100
- E:
false true nil
想知道答案的可以給公眾號傳送訊息bsf
獲取答案。
總結
Go語言的這個特性也引起了很多爭議,正如Go的錯誤處理一樣。
我們作為使用者,需要注意:Go不允許把關鍵字作為識別符號,其它都可以作為識別符號。
開源地址
文章和示例程式碼開源在GitHub: Go語言初級、中級和高階教程。
公眾號:coding進階。關注公眾號可以獲取最新Go面試題和技術棧。
個人網站:Jincheng's Blog。
知乎:無忌。