Go 讀者提問(wèn):值為 nil 能調(diào)用函數(shù)嗎?
大家好,我是煎魚(yú)。
最近在我們 Go 的技術(shù)交流群里,有一個(gè)小伙伴提了一個(gè)程序方面的問(wèn)題,還挺有意思的,分享給大家。

示例
示例程序如下:
type?T?struct{}
func?(t?*T)?Hello()?string?{
?if?t?==?nil?{
??fmt.Println("腦子進(jìn)煎魚(yú)了")
??return?""
?}
?return?"煎魚(yú)進(jìn)腦子了"
}
func?main()?{
?var?t?*T
?t.Hello()
這段程序的運(yùn)行結(jié)果是什么?
從程序的分析來(lái)看,變量 t 并沒(méi)有初始化,只是聲明了類型。然后就直接調(diào)用了 Hello 方法,像是 nil 調(diào)用函數(shù),理論上應(yīng)該出現(xiàn)恐慌(panic)。
運(yùn)行結(jié)果是:
panic:?runtime?error:?invalid?memory?address?or?nil?pointer?dereference
對(duì)不對(duì)呢?
顯然,真正的運(yùn)行結(jié)果是:
腦子進(jìn)煎魚(yú)了
請(qǐng)你思考一下,想想這是為什么?
為什么
問(wèn)題的原因是:很多小伙伴認(rèn)為變量 t 的值都是 nil 了,不應(yīng)該還能調(diào)用到才對(duì)。
更抽象化來(lái)講,就是 ”程序是如何檢查對(duì)象指針來(lái)尋找和調(diào)度所需函數(shù)“。
實(shí)際上,在 Go 中表達(dá)式 Expression.Name 的語(yǔ)法,所調(diào)用的函數(shù)完全由 Expression 的類型決定。
其調(diào)用函數(shù)的指向不是由該表達(dá)式的特定運(yùn)行時(shí)值來(lái)決定,包括我們前面所提到的 nil。
具體如下:
func?(p?*Sometype)?Somemethod?(firstArg?int)?{}
本質(zhì)上是:
func?SometypeSomemethod(p?*Sometype,?firstArg?int)?{}
這么一看,其實(shí)大家應(yīng)該都明白了。
上述入?yún)?p *Sometype 是有具體上下文類型的,自然而然也就能調(diào)用到相應(yīng)的方法。如果是沒(méi)有任何上下文類型的,例如:nil.Somemethod 方法來(lái)調(diào)用,那肯定就是無(wú)法運(yùn)行的。
與值是不是 nil,是什么,沒(méi)有太多直接的影響。只要有預(yù)期的上下文類型就可以了。
總結(jié)
今天給大家分享了一個(gè) Go 語(yǔ)言里面的一個(gè)小細(xì)節(jié),平時(shí)可能很多人沒(méi)注意到,畢竟 IDE 也會(huì)標(biāo)黃,會(huì)避開(kāi)這個(gè)問(wèn)題點(diǎn)。
在理解 Go 的設(shè)計(jì)和思考上,我們是需要清晰其背后的原因和邏輯的,也就是類型決定其調(diào)用,而不是值(容易誤判)。
你有沒(méi)有遇到過(guò)其它的細(xì)節(jié)問(wèn)題呢,歡迎交流:)
關(guān)注煎魚(yú),獲取業(yè)內(nèi)第一手消息和知識(shí) ??

你好,我是煎魚(yú),出版過(guò) Go 暢銷(xiāo)書(shū)《Go 語(yǔ)言編程之旅》,再到獲得 GOP(Go 領(lǐng)域最有觀點(diǎn)專家)榮譽(yù),點(diǎn)擊藍(lán)字查看我的出書(shū)之路。
日常分享高質(zhì)量文章,輸出 Go 面試、工作經(jīng)驗(yàn)、架構(gòu)設(shè)計(jì),加微信拉讀者交流群,和大家交流!
