在 go 中使用 range 遍历二维切片时,迭代变量是元素的副本而非引用,直接赋值不会修改原切片;需通过索引(如 grid[i] = ...)显式更新底层数组。
在 go 中使用 range 遍历二维切片时,迭代变量是元素的副本而非引用,直接赋值不会修改原切片;需通过索引(如 grid[i] = ...)显式更新底层数组。
Go 的切片是引用类型,但其本身是包含底层数组指针、长度和容量的结构体值。当使用 for _, row := range grid 时,row 是 grid[i](即一个 []string)的独立副本——它指向同一底层数组(若已初始化),但重新赋值 row = []string{...} 仅改变该局部变量的指向,对 grid 中对应位置毫无影响。更关键的是,此赋值后 row 未被读取,触发编译器“declared and not used”错误。
要正确初始化二维切片,必须通过索引显式赋值:
grid := make([][]string, 2) // 创建长度为 2 的切片,每个元素为 nil []string
for i := range grid {
grid[i] = []string{"foo", "bar"} // ✅ 正确:直接设置 grid 的第 i 个元素
}
fmt.Println(grid)
// 输出: [[foo bar] [foo bar]]
⚠️ 注意事项:
- make([][]string, 2) 仅分配外层切片空间,内部每个 []string 仍为 nil,不可直接对其调用 append 或索引访问;
- 若需预分配内层容量,可进一步优化:grid[i] = make([]string, 2); grid[i][0], grid[i][1] = "foo", "bar";
- 使用 for i, row := range grid 时,row 仍为副本,修改 row 内容(如 row[0] = "baz")仅在 row 已指向有效底层数组时生效(例如先执行 grid[i] = make([]string, 2)),但此写法易混淆,推荐优先使用索引赋值以保证清晰性与安全性。
总结:Go 中 range 迭代产生的是值拷贝,二维切片初始化必须通过下标索引操作原结构;理解切片的“结构体值 + 底层引用”双重特性,是避免此类陷阱的关键。











