nil的奇怪行為
剛接觸golang時,發現nil在不同的上下文,行為表現是不同的,並且和其他語言中的表現,也不大相同
實例1:輸入true, true, false,不符合傳遞性
func main() {
var t *T
var i interface{} = t
fmt.Println(t == nil, i == t, i == nil)
}
實例2:nil可以調用方法
func(t *tree) Sum() int {
if t == nil {
return 0
}
return t.v + t.l.Sum() + t.r.Sum()
}
var t *tree
t.Sum()
理解nil
golang中的nil與其他語言中的語義是一樣的,就是代表引用類型的默認值,但是不一樣的是,golang中有多種引用類型:pointer、interface、slice、map,channel, function;因此,每種引用類型的默認值,是不一樣的,就和基礎類型中,bool的默認值是false, int的默認值是0一樣
作為一個強類型語言,不同引用類型的判空(nil)規則是不同的;
-
interface的判空規則是,需要判斷類型和值是否都為nil(interface的底層是有類型和值構成的)
-
slice的判空,需要判斷slice引用底層數組的指針為空,容量和size均為0
因此,判斷nil的行為時,需要結合nil指向的具體類型,然后做判斷;比如實例1中,t是指針,i是interface, i中的數據類型是*T, 值為nil, 但是因為有類型,所有i不為nil; 實例2中,nil指針能夠直接調用方法,也是指針的語言特性
總結
理解nil,不能像理解其他語言中的null一樣,統一的去看待,需要結合具體的數據類型,然后改數據類型的語言特性去理解;
歷史上,null是一個偷懶的設計,雖然理解上很簡單,但是導致了許多問題,現代編程語言針對null,都有着自己的改進,比如java中的optional; nil的特性,也體現了golang開發者對null改進的獨特思考,由於沒有歷史包袱,設計可能比較獨特,和其他語言差別較大,初上手時可能比較難理解,但是熟悉后,就能感受到其帶來的便捷