如何理解golang中的nil

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)規則是不同的;

  1. interface的判空規則是,需要判斷類型和值是否都為nil(interface的底層是有類型和值構成的)

  2. 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改進的獨特思考,由於沒有歷史包袱,設計可能比較獨特,和其他語言差別較大,初上手時可能比較難理解,但是熟悉後,就能感受到其帶來的便捷

參考鏈接

理解Go語言的nil – 簡書

interface{}與nil,違背了==的傳遞性 – Golang 中國

Tags: