Go 提問:值為 Nil 能調用函數嗎?
本文轉載自微信公眾號「腦子進煎魚了」,作者陳煎魚。轉載本文請聯系腦子進煎魚了公眾號。
大家好,我是煎魚。
最近在我們 Go 的技術交流群里,有一個小伙伴提了一個程序方面的問題,還挺有意思的,分享給大家。
示例
示例程序如下:
- type T struct{}
- func (t *T) Hello() string {
- if t == nil {
- fmt.Println("腦子進煎魚了")
- return ""
- }
- return "煎魚進腦子了"
- }
- func main() {
- var t *T
- t.Hello()
這段程序的運行結果是什么?
從程序的分析來看,變量 t 并沒有初始化,只是聲明了類型。然后就直接調用了 Hello 方法,像是 nil 調用函數,理論上應該出現恐慌(panic)。
運行結果是:
- panic: runtime error: invalid memory address or nil pointer dereference
對不對呢?
顯然,真正的運行結果是:
- 腦子進煎魚了
請你思考一下,想想這是為什么?
為什么
問題的原因是:很多小伙伴認為變量 t 的值都是 nil 了,不應該還能調用到才對。
更抽象化來講,就是 ”程序是如何檢查對象指針來尋找和調度所需函數“。
實際上,在 Go 中表達式 Expression.Name 的語法,所調用的函數完全由 Expression 的類型決定。
其調用函數的指向不是由該表達式的特定運行時值來決定,包括我們前面所提到的 nil。
具體如下:
- func (p *Sometype) Somemethod (firstArg int) {}
本質上是:
- func SometypeSomemethod(p *Sometype, firstArg int) {}
這么一看,其實大家應該都明白了。
上述入參 p *Sometype 是有具體上下文類型的,自然而然也就能調用到相應的方法。如果是沒有任何上下文類型的,例如:nil.Somemethod 方法來調用,那肯定就是無法運行的。
與值是不是 nil,是什么,沒有太多直接的影響。只要有預期的上下文類型就可以了。
總結
今天給大家分享了一個 Go 語言里面的一個小細節,平時可能很多人沒注意到,畢竟 IDE 也會標黃,會避開這個問題點。
在理解 Go 的設計和思考上,我們是需要清晰其背后的原因和邏輯的,也就是類型決定其調用,而不是值(容易誤判)。