What is the correct way to check nil pointer de-reference?

Issue

To illustrate the question:

Say you’ve got the following struct with a method display (value receiver) that is meant to print the contents:

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

The above execution will error on the final loop since I’ve tried to de-reference nil with this output:

2 ->4 ->3 ->panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x109ae6f]

However, changing the function to a pointer receiver, it elegantly becomes:

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

with a happy output of:

2 ->4 ->3 ->

As a “newbie” to go, I figured since the display() function is read only, it would be best to write the function with a value receiver, but run into this issue. Is there a more elegant solution with a value receiver I’m missing or a better way to de-reference in the original function?

Solution

There is no point in testing the address of a value receiver to see if it is nil like this:

 for &l != nil {

Here, l is a variable with a value, and it can never be nil.

If you get a pointer receiver, this will do it, and will work even when l is nil:

func (l *ListNode) display() {
   for trc:=l; trc!=nil; trc=trc.Next {
        fmt.Printf("%v ->", trc.Val)
    }
}

If you get a value receiver:

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

Answered By – Burak Serdar

Answer Checked By – Terry (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.