考慮以下簡化示例:
package main
import (
"fmt"
)
type IMessenger interface {
Message()
}
type TMyMessenger struct {
}
func (m TMyMessenger) Message() {}
func MessengerFactory() IMessenger {
return getInternalMessengerVariant()
}
func getInternalMessengerVariant() *TMyMessenger {
return nil
}
func main() {
e := MessengerFactory()
fmt.Println(" e == nil", e == nil) // *TMyMessenger(nil)
if e != nil {
e.Message()
}
}
它的輸出:
e == nil false
panic: runtime error: invalid memory address or nil pointer dereference
問題 1:
是否有一種慣用的 Go 方法來檢查是否e指向 nil 指標?
最好是行內代碼段。在示例情況下,e != nil基本上使。false
我所考慮的:
如果
getInternalMessengerVariant()回傳介面型別而不是具體指標,則不會出現此問題,但它需要重構并且可能仍然未被檢測到并且在運行時將自身作為恐慌(如果 e != nil)。func getInternalMessengerVariant() IMessenger { return nil }重寫 MessengerFactory() 以攔截內部回傳:
func MessengerFactory() IMessenger { if m := getInternalMessengerVariant(); m != nil { return m } return nil }在型別檢查上要非常具體,但是如果有很多型別怎么辦:
if e != nil && e != (*TMyMessenger)(nil) { e.Message() }
uj5u.com熱心網友回復:
每當您從函式回傳介面時,就會存在此問題:如果介面包含型別化的 nil 指標,則介面本身不是 nil。沒有簡單的方法可以檢查。
解決這個問題的一個好方法是為介面回傳一個 nil:
func MessengerFactory() IMessenger {
x:= getInternalMessengerVariant()
if x==nil {
return nil
}
return x
}
然后您將不需要檢查回傳值是否指向 nil 指標。
uj5u.com熱心網友回復:
Burak Serdar 在他的回答中很好地解釋了為什么會為您if x == nil回傳false。
但這不是你感到恐慌的原因。
Go 很樂意在nil指標上呼叫接收器函式,只要接收器不取消參考指標。
這并不驚慌:
type TMyMessenger struct {
}
func (m *TMyMessenger) Message() {}
func main() {
var t *TMyMessenger = nil
t.Message()
}
那是因為您沒有取消參考接收器函式m內的指標。Message
您的示例只會出現恐慌,因為您已經m在型別TMyMessenger(而不是指標)上定義了接收器函式。因此,Go 必須取消參考指向介面值內部的nil指標TMyMessenger,IMessenger才能呼叫接收器函式。
如果您更改代碼中的一行,它將不再恐慌:
func (m *TMyMessenger) Message() {}
(更改(m TMyMessenger)為(m *TMyMessenger))
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/506491.html
上一篇:按值或按參考回傳類
下一篇:為什么這個程式有效?
