Go: Struct Maps Require Initialization

Testing some go code that updates the value of map contained in a struct, I encountered an error I had not seen before:

panic: assignment to entry in nil map

One of the things I really like about Go is that, owing to its consistency, it usually adheres to The Principle Of Least Surprise.

To start with, here’s a snippet of the error:

package main

type T struct {
	Data map[string]int
}

func main() {
	t := T{}
	t.Data["key"] += 5
	// panic: assignment to entry in nil map
}

The reason this was surprising to me is that the zero value does not require initialization for an array of ints contained in a struct:

type T struct {
	Data []int
}

func main() {
	t := T{}
	t.Data = append(t.Data, 5)
	fmt.Println(t.Data)
	// prints [5]
}

Turns out my case fails is because the uninitialized map is actually nil:

type T struct {
	Data map[string]int
}

func main() {
	t := T{}
	fmt.Println(t.Data == nil)
	// prints true
}

The fix is to initialize the map (shown here with a constructor) before using it:

type T struct {
	Data map[string]int
}

func NewT() *T {
	return &T{
		Data: make(map[string]int),
	}
}

func main() {
	t := NewT()
	t.Data["key"] += 5
	fmt.Println(t.Data["key"])
	// prints 5
}