
在go中,对未初始化的map进行赋值操作(如m[key] = value)会触发运行时panic,无论map的键类型是基本类型、结构体还是嵌套map,根本原因在于nil map不具备底层哈希表结构,无法执行写入操作。
在go中,对未初始化的map进行赋值操作(如m[key] = value)会触发运行时panic,无论map的键类型是基本类型、结构体还是嵌套map,根本原因在于nil map不具备底层哈希表结构,无法执行写入操作。
Go语言中的map是引用类型,但其零值为nil。与切片不同,nil map不可读写——即使只读操作(如v, ok := m[k])是安全的,但任何写入行为(包括赋值、删除、清空)都会立即引发panic: assignment to entry in nil map。
在你的示例中:
type COO struct {
x int
y int
}
var neighbours map[COO][]COO // ← 零值为 nil
func main() {
// ...
neighbours[COO{x: i, y: j}] = buds // panic!
}尽管COO是结构体类型(可比较、可作map键),但neighbours本身未通过make()初始化,因此仍是nil map。该panic与键的复杂度无关——即使是map[string]int,若未初始化也必然panic。
✅ 正确做法:使用make显式初始化:
立即学习“go语言免费学习笔记(深入)”;
var neighbours = make(map[COO][]COO) // 推荐:声明+初始化一行完成 // 或 neighbours := make(map[COO][]COO) // 短变量声明(限函数内)
⚠️ 注意事项:
- make(map[K]V) 是唯一安全创建可写map的方式;new(map[K]V) 返回的是指向nil map的指针,仍不可用;
- 初始化后可任意增删改查,无需再次检查nil;
- 若需延迟初始化(如根据条件创建),务必在首次写入前确保已调用make;
- 对于嵌套map(如map[string]map[int]bool),外层map需make,但内层map仍需单独初始化(如m[k] = make(map[int]bool)),否则m[k][i] = true会panic。
修复后的完整示例:
package main
import "fmt"
type COO struct {
x int
y int
}
func main() {
neighbours := make(map[COO][]COO) // ✅ 初始化
for i := 0; i < 30; i++ {
for j := 0; j < 20; j++ {
var buds []COO
if i < 29 {
buds = append(buds, COO{x: i + 1, y: j})
}
if i > 0 {
buds = append(buds, COO{x: i - 1, y: j})
}
if j < 19 {
buds = append(buds, COO{x: i, y: j + 1})
}
if j > 0 {
buds = append(buds, COO{x: i, y: j - 1})
}
neighbours[COO{x: i, y: j}] = buds // ✅ 安全写入
}
}
fmt.Printf("neighbours size: %d\n", len(neighbours))
}总结:Go中所有map必须显式初始化才能写入,这是语言设计的明确约束,而非bug或特例。养成“声明即初始化”习惯(如:= make(...)),可彻底避免此类panic。


















