go 语言中,数组作为 map 键时会被完整复制(值语义),修改原数组不会影响 map 中已存的键;这是因为数组是值类型,插入时 map 会持有其独立副本。
go 语言中,数组作为 map 键时会被完整复制(值语义),修改原数组不会影响 map 中已存的键;这是因为数组是值类型,插入时 map 会持有其独立副本。
在 Go 中,所有数组都是值类型(value types),这意味着它们在赋值、传参或用作 map 键时,会进行完整的内存拷贝——即“深拷贝”(严格来说是按字节逐位复制,对数组而言等价于深拷贝)。这与 slice、map 或 struct 中含指针字段的情况有本质区别。
以你提供的示例为例:
m := make(map[[2][3]int]int)a := [2][3]int{{1, 2, 3}, {4, 5, 6}}m[a] = 1
此处 a 是一个长度为 2、元素类型为 [3]int 的二维数组,总大小固定(2 × 3 × int = 通常 48 字节)。当执行 m[a] = 1 时,Go 运行时会将 a 的全部字节内容复制一份,作为 map 内部哈希表中该键的存储值。此后 a 的任何修改(如 a[0][0] = 99)均不影响 map 中已存在的键:
a[0][0] = 99fmt.Println(m[a]) // 输出 0(未找到),因为此时 a 已改变,不再是原键fmt.Println(m[[2][3]int{{1, 2, 3}, {4, 5, 6}}]) // 输出 1,原始键仍有效
✅ 正确理解的关键点:
⚠️ 注意事项:
总之:Go map 对数组键执行的是完整、独立、不可变的值拷贝——这是由其值类型语义决定的底层保证,也是编写可预测、线程安全映射逻辑的基础。