assignment to entry in nil map の原因と直し方
makeで初期化していないnilのマップに要素を書き込もうとすると、実行時にパニックが発生します。マップのゼロ値はnilで、読み取りはできても書き込みはできません。
エラーメッセージの読み方
panic: assignment to entry in nil map
panic- パニック — 実行時に回復不能な状態になったことを示します。deferとrecoverで捕まえない限り、そのままプロセスが終了します
assignment to entry in nil map- 詳細メッセージ — どの値が問題だったか
このエラーが出る典型パターン
パターン1
1 package main 2 3 func main() { 4 var m map[string]int ^ 5 m["a"] = 1 6 }
var mで宣言しただけのマップはnilで、要素の読み取りはできても書き込みはできません。makeで初期化する必要があります。
直し方: var m map[string]int を m := make(map[string]int) にします。
パターン2
1 package main 2 3 func main() { 4 var m map[string]int ^ 5 m["total"] = 100 6 }
マップのゼロ値はnilです。書き込みを行う前に必ずmakeで実体を作る必要があります。
直し方: var m map[string]int を m := make(map[string]int) にします。
パターン3
1 package main 2 3 func main() { 4 var m map[string]string ^ 5 m["name"] = "go" 6 }
値の型がstringでも同じで、nilマップへの書き込みは型によらずパニックします。
直し方: var m map[string]string を m := make(map[string]string) にします。
パターン4
1 package main 2 3 func main() { 4 var m map[int]string ^ 5 m[1] = "one" 6 }
キーの型がintでも同様に、初期化前のnilマップへの書き込みはパニックの原因になります。
直し方: var m map[int]string を m := make(map[int]string) にします。
パターン5
1 package main 2 3 func main() { 4 var m map[string]bool ^ 5 m["ok"] = true 6 }
読み取り専用の用途ならnilマップでも動きますが、書き込みが必要な時点でmakeによる初期化が必須です。
直し方: var m map[string]bool を m := make(map[string]bool) にします。
よくある誤解
「var で宣言した時点で、マップは空の状態で書き込み可能になっているはず」という思い込みは誤りです。マップのゼロ値はnilであり、make(map[K]V)で明示的に初期化しない限り要素を追加できません。
まとめ
assignment to entry in nil mapは初級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。