在 Go 中使用 range 遍历二维切片时,若直接对迭代变量赋值,无法修改原切片元素——因为切片本身是引用类型,但 range 返回的是每个子切片的副本,而非指向底层数组的引用。
在 go 中使用 `range` 遍历二维切片时,若直接对迭代变量赋值,无法修改原切片元素——因为切片本身是引用类型,但 `range` 返回的是每个子切片的**副本**,而非指向底层数组的引用。
Go 的切片(slice)是一个包含底层数组指针、长度和容量的结构体。当你用 for _, row := range grid 遍历时,row 是 grid[i] 的值拷贝(即一个新的 slice header),对 row 重新赋值(如 row = []string{"foo", "bar"})仅修改了该局部变量,不会影响 grid 中对应位置的原始 slice。此外,该赋值后 row 未被后续使用,因此编译器报错 row declared and not used。
✅ 正确做法是通过索引显式赋值:
grid := make([][]string, 2)
for i := range grid {
grid[i] = []string{"foo", "bar"}
}
fmt.Println(grid)
// 输出:[[foo bar] [foo bar]]
这里 i 是索引(0 和 1),grid[i] 直接访问并更新底层数组中的 slice header,从而完成初始化。
⚠️ 注意事项:
- make([][]string, 2) 仅分配了外层切片(长度为 2),其每个元素初始值为 nil;必须显式为每个 grid[i] 分配内存(如 make([]string, 2) 或字面量 []string{...})。
- 若需预分配内层数组长度,可写为:
grid := make([][]string, 2) for i := range grid { grid[i] = make([]string, 2) // 每行长度为 2 grid[i][0], grid[i][1] = "foo", "bar" } - 使用 for i := 0; i
总结:Go 中 range 迭代切片时,迭代变量是值拷贝;要修改原切片内容,务必通过索引(slice[i])操作。理解 slice 的“头信息+底层数组”模型,是避免此类陷阱的关键。











