😕

[Golang] nil map には要素を追加できない

ひっかかったのでメモ。


起こったこと

map を定義して、そこに要素を追加しようとしたら panic になった。

var m map[string]int
m["route"] = 66

// panic: assignment to entry in nil map

常にゼロ値が返ってくるものの、参照はできる。

var m map[string]int
v, exists := m["root"]
// 0, false

nil map とは

nil map とは、参照型である map がまだ初期化されていない (メモリが確保されていない) 状態。 要素を追加できるようにするには、make() を使って map を初期化する必要がある。

こうして使う

m := make(map[string]int)

m["route"] = 66

もしあらかじめ値を入れておきたいなら、以下のように定義してもいい。

m := map[string]int{
    "route": 66,
}

ちなみに

nil slice ならどうなるか。

まず、参照はできない。ゼロ値は返ってこない。

var s []int
num := s[0]
// panic: runtime error: index out of range [0] with length 0

追加はできる。ただし、append() を使う必要がある。

var s []int
s[0] = 10
// panic: runtime error: index out of range [0] with length 0

s = append(s, 10)

append() は slice のメモリ確保量が足りないときに、メモリを確保し直してくれる機能がついているから、nil slice にも値を追加できる。 実際、nil slice に値を追加する前後で cap が増えている、つまり、メモリが再確保されていることがわかる。

var s []int
fmt.Println(cap(s)) // 0

s = append(s, 10)
fmt.Println(cap(s)) // 1

詳しくは slice と array を理解する へ。


値型なのか参照型なのかをきっちり見極めないとこういうことが起きる 🙃