检查 nil 指针取消引用的正确方法是什么?

为了说明这个问题:


假设您有以下结构体,其中包含用于打印内容的方法 display (值接收器):


type ListNode struct {

    Val  int

    Next *ListNode

}



func (l ListNode) display() {

    for &l != nil {

        fmt.Printf("%v ->", l.Val)

        l = *l.Next

    }

    fmt.Println()

}


func main() {

    num1 := ListNode{2, &ListNode{4, &ListNode{3, nil}}}


    num1.display()

}


上面的执行将在最后一个循环中出错,因为我尝试使用以下输出取消引用 nil:


2 ->4 ->3 ->panic: runtime error: invalid memory address or nil pointer dereference

[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x109ae6f]

然而,将函数更改为指针接收器,它会优雅地变为:


func (l *ListNode) display() {

    for l != nil {

        fmt.Printf("%v ->", l.Val)

        l = l.Next

    }

    fmt.Println()

}

愉快的输出:


2 ->4 ->3 ->

作为一个“新手”,我认为由于该display()函数是只读的,因此最好使用值接收器编写该函数,但遇到了这个问题。是否有一个更优雅的解决方案以及我缺少的值接收器或在原始函数中取消引用的更好方法?


月关宝盒
浏览 140回答 4
4回答

炎炎设计

像这样测试值接收者的地址来查看它是否为 nil 是没有意义的: for &l != nil {这里,l是一个有值的变量,它永远不能为零。如果你有一个指针接收器,这将做到这一点,并且即使在lnil 时也能工作:func (l *ListNode) display() {   for trc:=l; trc!=nil; trc=trc.Next {        fmt.Printf("%v ->", trc.Val)    }}如果你得到一个值接收者:func (l ListNode) display() {   for trc:=&l; trc!=nil; trc=trc.Next {        fmt.Printf("%v ->", trc.Val)    }}

繁花不似锦

以下是指针取消引用:v = *ptr如果 ptr 为零,这将崩溃。在取消引用之前检查是否为零。if ptr != nil {    v = *ptr    // ...... }

蛊毒传说

您拥有值接收器的事实不会改变您拥有指针字段的事实。并且您不需要将它们的形式强制为接收者的形式(值/指针)。他们可以保留指针。无需(显式)取消引用。func (l ListNode) display() {    curNode := &l    for curNode != nil {        fmt.Printf("%v ->", curNode.Val)        curNode = curNode.Next    }    fmt.Println()}

慕标琳琳

某种递归解决方案package mainimport "fmt"type ListNode struct {    Val  int    Next *ListNode}func (l *ListNode) display() {    if l != nil {        fmt.Printf("%v ->", l.Val)        l.Next.display()    }    fmt.Println()}func main() {    num1 := &ListNode{2, &ListNode{4, &ListNode{3, nil}}}    num1.display()}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go