Invalid memory address or nil pointer dereference when appending to slice of structs

go, slice, struct

Solution

For example,

package main

import (
    "fmt"
)

type Person struct {
    name string
}

func main() {
    p := make([]*Person, 1) //Changed to 1 instead of 0
    fmt.Println(len(p), p)
    p = append(p, &Person{"Brian"})
    fmt.Println(len(p), p)
    fmt.Println(p[1].name)
    fmt.Println(p[0])
    fmt.Println(p[0].name)
}

Output:

1 [<nil>]
2 [<nil> 0x10500190]
Brian
<nil>
panic: runtime error: invalid memory address or nil pointer dereference

`p` has length 1 before the append, length 2 after. Therefore, `p[0]` has the uninitialized pointer value `nil` and `p[0].name` is invalid.

The Go Programming Language Specification

Appending to and copying slices

The variadic function append appends zero or more values x to s of type S, which must be a slice type, and returns the resulting slice, also of type S.

Pointer types

The value of an uninitialized pointer is nil.

Selectors

The following rules apply to selectors:

4) If x is of pointer type and has the value nil and x.f denotes a struct field, assigning to or evaluating x.f causes a run-time panic.

Problem

``` package main import ( "fmt" ) type Person struct { name string } func main() { p := make([]*Person, 0) p = append(p, &Person{"Brian"}) fmt.Println(p[0].name) p = append(p, &Person{"Le Tu"}) fmt.Println(p[1].name) } ``` The above works fine. ``` package main import ( "fmt" ) type Person struct { name string } func main() { p := make([]*Person, 1) //Changed to 1 instead of 0 p = append(p, &Person{"Brian"}) fmt.Println(p[0].name) p = append(p, &Person{"Le Tu"}) fmt.Println(p[1].name) } ``` The above panics. My understanding of `append` was that it hid the mechanics of extending/adding. Clearly, my mental model of using `append` as a sort of "push" for slices is incorrect. Can anyone explain to me why the second sample above panics? Why can't I just `append` my struct?

Original source