golang 中 map 嵌套 struct 时,字段不能直接复制的原因
map 中嵌套 struct 时,struct 中的字段是不能被直接赋值的。举个例子:
package main
import "fmt"
type Person struct {
name string
age int
}
func main() {
m := map[int]Person{
1: Person{"Andy", 10},
2: Person{"Tiny", 20},
3: Person{"Jack", 30},
}
m[1].name = "KL" // ① err
m[1] = Person{"Tom", 40} // ② 正确
}
为什么会这样呢?原因在于 map 的 value 是不能被取地址的,struct 的点操作符会先查找 m[1]
的地址,再计算偏移量,最后修改对应位置的字段。但对 m[1]
取地址在 map 中是不被允许的,因为 map 可能随着元素数量的增长而重新分配更大的内存空间,从而可能导致之前的地址无效。故而 ① 错误。
网上说 x = y 赋值时,也需要先知道 x 的地址才能赋值,那为什么 ② 正确呢?② 不也对 m[1]
取了地址吗?其实,对于 ②,可以理解为 map 重新对 key = 1 进行哈希运算,计算出桶的位置,而后用新的值 Person{"Tom", 40}
覆盖掉了原先的 Person{"Andy", 10}
,相当于旧值不存在。这个过程中并没有直接对 m[1]
取地址。