首页 > 解决方案 > 检查 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()函数是只读的,因此最好使用值接收器编写该函数,但会遇到这个问题。是否有一个更优雅的解决方案与我缺少的值接收器或在原始函数中取消引用的更好方法?

标签: listpointersgostructlinked-list

解决方案


像这样测试值接收器的地址以查看它是否为 nil 是没有意义的:

 for &l != nil {

这里,l是一个有值的变量,它永远不能为零。

如果你得到一个指针接收器,这会做到,并且即使l是 nil 也能工作:

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)
    }
}

推荐阅读