1. 读写 nil Map 的区别(最阴的地方)
在 Go 语言中,nil Map 的行为极其分裂:
- 读
nilMap:不会报错! 它会返回该类型的"零值"。- 例如:
var m map[string]int(此时 m 是 nil),你执行v := m["abc"],v就是0。
- 例如:
- 写
nilMap:必崩(Panic)!- 执行
m["abc"] = 123,程序直接挂掉,报错panic: assignment to entry in nil map。
- 执行
2. 多级 Map 必须"层层开门"
如果结构是 map[string]map[string]int。这就像个套间,你开了大门的锁,不代表里面的房门也是开着的。
// 错误写法
m := make(map[string]map[string]int)
m["device"]["pc"] = 1 // 必崩!因为 m["device"] 还是 nil
// 正确写法
m := make(map[string]map[string]int)
if m["device"] == nil {
m["device"] = make(map[string]int) // 先把内层小房间开好
}
m["device"]["pc"] = 1 // 稳如老狗
3. 如何优雅地避坑?(通天代习惯)
在写 复杂的聚合逻辑时,建议养成"检查并初始化"的一体化习惯。
你可以写一个简单的辅助闭包或者直接在逻辑里:
func (l *FlowLogic) ensureMap(m map[string]map[string]int, pCode string) {
if _, ok := m[pCode]; !ok {
m[pCode] = make(map[string]int)
}
}
每次写入前调一下,或者直接用 if ok 判断。
额外赠礼:PHP 到 Go 的"后遗症"
- PHP:
$a['b']['c'] = 1;------ PHP 会自动帮你把b这一层创建出来(Autovivification)。 - Go:没有自动创建! 你必须手动
make每一层。如果你带着 PHP 的习惯去写 Go,你的程序会像鞭炮一样到处 Panic。