《Go語言四十二章經》第三章 變數
《Go語言四十二章經》第三章 變數
作者:李驍
3.1 變數以及宣告
Go 語言變數名由字母、數字、下劃線組成,其中首個字母不能為數字。
var ( a int b bool str string )
這種因式分解關鍵字的寫法一般用於宣告全域性變數,一般在func 外定義。
當一個變數被var宣告之後,系統自動賦予它該型別的零值:
- int為 0
- float為 0.0
- bool為 false
- string 為空字串""
- 指標為 nil
記住,這些變數在 Go 中都是經過初始化的。
多變數可以在同一行進行賦值,也稱為 並行 或 同時 或 平行賦值。如:
a, b, c = 5, 7, "abc"
簡式宣告:
a, b, c := 5, 7, "abc"// 注意等號前的冒號
右邊的這些值以相同的順序賦值給左邊的變數,所以 a 的值是 5, b 的值是 7,c 的值是 "abc"。
簡式宣告一般用在func內,要注意的是:全域性變數和簡式宣告的變數儘量不要同名,否則很容易產生偶然的變數隱藏Accidental Variable Shadowing。
即使對於經驗豐富的Go開發者而言,這也是一個非常常見的陷阱。這個坑很容易挖,但又很難發現。
func main() { x := 1 fmt.Println(x)// prints 1 { fmt.Println(x) // prints 1 x := 2 fmt.Println(x) // prints 2 } fmt.Println(x)// prints 1 (不是2) }
如果你想要交換兩個變數的值,則可以簡單地使用:
a, b = b, a
(在 Go 語言中,這樣省去了使用交換函式的必要)
空白識別符號 _ 也被用於拋棄值,如值 5 在:_, b = 5, 7
中被拋棄。
_, b = 5, 7
_ 實際上是一個只寫變數,你不能得到它的值。這樣做是因為 Go 語言中你必須使用所有被宣告的變數,但有時你並不需要使用從一個函式得到的所有返回值。
由於Go語言有個強制規定,在函式內一定要使用宣告的變數,但未使用的全域性變數是沒問題的。為了避免有未使用的變數,程式碼將編譯失敗,我們可以將該未使用的變數改為 _。
另外,在Go語言中,如果引入的包未使用,也不能通過編譯。有時我們需要引入的包,比如需要init(),或者除錯程式碼時我們可能去掉了某些包的功能使用,你可以新增一個下劃線標記符,_,來作為這個包的名字,從而避免編譯失敗。下滑線標記符用於引入,但不使用。
package main import ( _ "fmt" "log" "time" ) var _ = log.Println func main() { _ = time.Now }
並行賦值也被用於當一個函式返回多個返回值時,比如這裡的 val 和錯誤 err 是通過呼叫 Func1 函式同時得到:
val, err = Func1(var1)
對於布林值的好的命名能夠很好地提升程式碼的可讀性,例如以 is 或者 Is 開頭的 isSorted、isFinished、isVisible,使用這樣的命名能夠在閱讀程式碼的獲得閱讀正常語句一樣的良好體驗,例如標準庫中的 unicode.IsDigit(ch)。
在 Go 語言中,指標屬於引用型別,其它的引用型別還包括 slices,maps和 channel。
注意,Go中的陣列是數值,因此當你向函式中傳遞陣列時,函式會得到原始陣列資料的一份複製。如果你打算更新陣列的資料,可以考慮使用陣列指標型別。
package main import "fmt" func main() { x := [3]int{1, 2, 3} func(arr *[3]int) { (*arr)[0] = 7 fmt.Println(arr) // prints &[7 2 3] }(&x) fmt.Println(x) // prints [7 2 3] }
被引用的變數會儲存在堆中,以便進行垃圾回收,且比棧擁有更大的記憶體空間。
引申:
編譯器會做逃逸分析,所以由Go的編譯器決定在哪(堆or棧)分配記憶體,保證程式的正確性。
3.2 零值nil
nil 標誌符用於表示interface、函式、maps、slices和channels的“零值”。如果你不指定變數的型別,編譯器將無法編譯你的程式碼,因為它猜不出具體的型別。
package main func main() { var x = nil // 錯誤 _ = x }
在一個 nil 的slice中新增元素是沒問題的,但對一個map做同樣的事將會生成一個執行時的panic:
package main func main() { var m map[string]int m["one"] = 1 //error }
字串不會為 nil
這對於經常使用 nil 分配字串變數的開發者而言是個需要注意的地方。
var str string= "" // ""是字串的零值
根據前面的介紹,其實這樣寫和上面的效果一樣:
var str string
本書《Go語言四十二章經》內容在github上同步地址:https://github.com/ffhelicopter/Go42