
在 Go 中,声明但未初始化的 map 是 nil 值,对其执行赋值操作(如 m[key] = value)会立即触发 panic: assignment to entry in nil map,无论 key 类型是基础类型、结构体还是嵌套 map。
在 go 中,声明但未初始化的 map 是 nil 值,对其执行赋值操作(如 `m[key] = value`)会立即触发 `panic: assignment to entry in nil map`,无论 key 类型是基础类型、结构体还是嵌套 map。
Go 的 map 是引用类型,但其零值为 nil——这不同于 slice(零值为 nil 但可安全调用 append)或 channel(零值为 nil 但需显式 make 才能发送/接收)。对 nil map 进行写操作(包括插入、更新、删除)均会导致运行时 panic,而读操作(如 v, ok := m[key])则是安全的,仅返回零值和 false。
在你的代码中:
var neighbours map[COO][]COO // ← 声明但未初始化,neighbours == nil
// ...
neighbours[COO{x: i, y: j}] = buds // ← 对 nil map 赋值 → panic!
尽管 COO 是结构体类型(支持作为 map key),但这与 panic 无关;真正的问题在于 neighbours 从未被 make 初始化。Go 不会自动为 map 分配底层哈希表,必须显式调用 make:
✅ 正确做法:
func main() {
neighbours := make(map[COO][]COO) // 推荐:短变量声明 + 初始化
// 或
// var neighbours = make(map[COO][]COO)
// 或
// neighbours := map[COO][]COO{}
for i := 0; i 0 {
buds = append(buds, COO{x: i - 1, y: j})
}
if j 0 {
buds = append(buds, COO{x: i, y: j - 1})
}
neighbours[COO{x: i, y: j}] = buds // ✅ 安全赋值
}
}
fmt.Println(len(neighbours)) // 输出 600
}
⚠️ 注意事项:
- map[COO][]COO{} 是字面量语法,等价于 make(map[COO][]COO),二者均可;
- 结构体作为 map key 时,要求其所有字段可比较(int 满足),无需额外实现接口;
- 若需预估容量以提升性能(尤其在大量写入前),可用 make(map[COO][]COO, 600) 指定初始桶数;
- 切勿依赖“零值 map 可读不可写”的模糊认知——应始终在首次写入前显式初始化。
总结:Go 中 map 的零值是 nil,不是空容器。任何写操作前,必须通过 make 或字面量完成初始化。这是 Go 内存安全设计的一部分,也是避免 runtime panic 的基本准则。











