
go 中数组是值类型,向 map 插入数组键时会进行完整复制;修改原数组变量不会影响 map 中已存储的键,因两者内存独立。
go 中数组是值类型,向 map 插入数组键时会进行完整复制;修改原数组变量不会影响 map 中已存储的键,因两者内存独立。
在 Go 中,所有数组都是值类型(value types),这意味着它们在赋值、函数传参或作为 map 键插入时,都会发生完整的内存拷贝——而非共享引用。这一特性直接决定了 map 对数组键的处理方式:插入时深拷贝整个数组结构(注意:此处“深拷贝”指按值语义的完整复制,不涉及指针间接层,因此对纯数组而言等价于深拷贝)。
例如,声明一个以二维数组为键的 map:
m := make(map[[2][3]int]int)
a := [2][3]int{{1, 2, 3}, {4, 5, 6}}
m[a] = 1此时,a 的全部 6 个整数值([2][3]int 共 2×3=6 个 int)被逐字节复制到 map 内部的键存储区。后续即使修改 a,也不会影响 map 中已存的键:
a[0][0] = 999 // 修改原数组
fmt.Println(m[[2][3]int{{1, 2, 3}, {4, 5, 6}}]) // 仍输出 1 —— 原始键值未变
fmt.Println(len(m)) // 仍为 1可通过地址对比验证该行为(注意:&k 在 range 中取的是迭代变量地址,非 map 内部键地址;但因其值与 a 完全相同且地址不同,足以证明副本存在):
for k := range m {
fmt.Printf("Key value: %+v\n", k) // {{1 2 3} {4 5 6}}
fmt.Printf("Address of k: %p\n", &k) // 地址与 &a 不同 → 独立副本
}✅ 关键结论:
- 数组键在插入 map 时被完整复制,与源变量完全解耦;
- 支持任意可比较类型(如数组、结构体、字符串等)作键,均遵循值语义;
- 若需避免复制开销,可改用指针(如 *[2][3]int)或切片+哈希预计算,但需自行保证键的不可变性与线程安全。
⚠️ 注意:此行为仅适用于数组;若使用切片([][]int)则无法作为 map 键(切片不可比较),而结构体中若含指针或 slice 字段,则其相等性取决于字段值而非地址——但数组字段始终按值比较与复制。


















