Go语言 检查空指针解引用的正确方法是什么?

njthzxwz  于 2022-12-07  发布在  Go
关注(0)|答案(4)|浏览(202)

为了说明这个问题:
假设你有一个结构体,它有一个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()函数是只读的,最好用一个值接收器来编写函数,但是遇到了这个问题。有没有一个更好的解决方案来使用我缺少的值接收器,或者在原始函数中取消引用的更好的方法?

56lgkhnf

56lgkhnf1#

测试值接收方的地址以查看它是否为空是没有意义的,如下所示:

for &l != nil {

这里,l是一个有值的变量,它永远不能为nil。
如果你有一个指针接收器,这就可以了,即使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)
    }
}
jaql4c8m

jaql4c8m2#

你有一个值接收器的事实并不会改变你有指针字段的事实。而且你不需要将它们的形式强制为接收器的形式(值/指针)。它们仍然可以是指针。不需要(显式地)解引用。

func (l ListNode) display() {
    curNode := &l
    for curNode != nil {
        fmt.Printf("%v ->", curNode.Val)
        curNode = curNode.Next
    }
    fmt.Println()
}
qmelpv7a

qmelpv7a3#

某种递归解法

package main

import "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()
}
yftpprvb

yftpprvb4#

下面是一个指针取消引用:

v = *ptr

如果ptr为nil,这将崩溃。在 * 取消引用之前检查nil *。

if ptr != nil {
    v = *ptr
    // ...... 
}

相关问题