Go语言中值为固定长度数组的map更新不生效是什么原因?
核心问题原因
- Go语言中数组属于值类型,从map中读取数组值时,会返回该数组的完整拷贝,你后续对拷贝变量的修改不会作用到map内存储的原始数组上。
- 另外Go禁止直接修改map的value元素:直接写
n.rebuilt[4][2] = 0会编译报错,因为map的value是不可寻址的,运行时可能因map扩容发生地址偏移,Go语言层面不允许直接修改map value的内部字段。
解决方案
方案1:修改后将副本重新赋值回map
改动最小,不需要修改原有结构体定义,修改完数组拷贝后手动把新值写回map对应key即可:
nbrs0 := n.rebuilt[4] nbrs1 := n.rebuilt[0] nbrs0[2] = 0 nbrs1[1] = 4 // 新增赋值逻辑,把修改后的数组写回map n.rebuilt[4] = nbrs0 n.rebuilt[0] = nbrs1
方案2:将map的value类型改为数组指针
修改结构体定义,把value改为数组指针类型,后续从map读取的是指针,修改指针对应的内容会直接作用到原始数据上,不需要额外回写:
// 修改结构体定义,value改为数组指针 type Neighborhood struct { rebuilt map[uint32]*[3]uint32 // Facet index vs {neighbor0, neighbor1, neighbor2} }
对应初始化逻辑也要调整:
n := &Neighborhood{ rebuilt: make(map[uint32]*[3]uint32, 9348), } // 初始化时存储数组指针 for i := uint32(0); i < 9348; i++ { n.rebuilt[i] = &[3]uint32{math.MaxUint32, math.MaxUint32, math.MaxUint32} }
原有修改代码可以直接生效,不需要额外改动。
方案3:将value替换为切片(可选)
切片是引用类型,也可以实现直接修改的效果,你如果后续长度可能变化可以用这个方案,固定长度3的场景下更推荐方案2:
type Neighborhood struct { rebuilt map[uint32][]uint32 } // 初始化时长度固定为3即可
内容的提问来源于stack exchange,提问作者Megidd
相关产品推荐
相关产品推荐

