为了账号安全,请及时绑定邮箱和手机立即绑定

在 Go 中处理指向 nil 指针的指针

在 Go 中处理指向 nil 指针的指针

Go
杨魅力 2023-02-06 14:51:01
考虑以下简化示例:package mainimport (    "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 falsepanic: 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()}
查看完整描述

2 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

每当您从函数返回接口时,都会存在此问题:如果接口包含类型化的 nil 指针,则接口本身不是 nil。没有简单的方法来检查它。


处理这个问题的一个好方法是为接口返回一个 nil:


func MessengerFactory() IMessenger {

    x:= getInternalMessengerVariant()

    if x==nil {

        return nil

    }

    return x

}

那么你就不需要检查返回值是否指向一个 nil 指针。


查看完整回答
反对 回复 2023-02-06
?
MMMHUHU

TA贡献1834条经验 获得超8个赞

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指针,以便调用接收函数。TMyMessengerIMessenger


如果您更改代码中的一行,它将不再恐慌:


func (m *TMyMessenger) Message()  {}

((m TMyMessenger)改为(m *TMyMessenger))


查看完整回答
反对 回复 2023-02-06
  • 2 回答
  • 0 关注
  • 188 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号