Go中二维切片是切片的切片,需先make外层再循环make内层;零值声明var matrix [][]int为nil,直接访问会panic;字面量可初始化不等长行,底层各自独立。

Go里声明二维切片的常见写法
Go没有内置的“多维数组类型”,所谓多维切片本质是切片的切片,比如 []string 是一维,[][]string 就是二维。声明时必须明确最外层维度,内层可以为空或后续追加。
最常用的是零值声明:var matrix [][]int —— 此时 matrix 是 nil 切片,长度为 0,不能直接用 matrix[i][j] 赋值,会 panic。
如果想立刻可用,得初始化外层并为每行分配内存:
matrix := make([][]int, 3) // 外层有3行
for i := range matrix {
matrix[i] = make([]int, 4) // 每行4列
}这样 matrix[0][0] 才能安全读写。
立即学习“go语言免费学习笔记(深入)”;
为什么不能直接 make([][]int, 3, 4)
make 只支持一维切片的容量参数,make([][]int, 3, 4) 语法合法但没意义:它只给外层切片分配了长度 3、容量 4 的底层数组,每个元素仍是 nil 的 []int,没分配内层空间。
常见错误现象:
- 运行时报 panic: runtime error: index out of range [0] with length 0
- 表面声明了二维结构,实际访问任意 [i][j] 都崩溃
正确做法始终是两步:
- make 外层切片
- 循环对每个元素再 make 内层切片
用字面量声明带初始值的二维切片
适合小规模、固定数据,比如测试数据或配置表:
grid := [][]bool{
{true, false, true},
{false, true, false},
{true, true, false},
}注意:
- 每一行的长度可以不同(Go 支持“锯齿数组”)
- 编译器自动推导类型,不用显式写 [][]bool
- 所有子切片共享底层?不,字面量中每行都是独立分配的底层数组
如果某行为空,写成 {} 或 nil 都合法,但行为不同:
- {} 是空切片(len=0, cap>0)
- nil 是未初始化切片(len=0, cap=0, ptr=nil)
动态追加行和列的注意事项
二维切片不是矩阵容器,它是“切片的切片”,所以增删操作粒度在外层元素上:
- 追加新行:
matrix = append(matrix, []int{1,2,3}) - 给第 0 行追加元素:
matrix[0] = append(matrix[0], 4) - 不能直接
append(matrix[0], 4)—— 因为append返回新切片,必须赋值回去
性能提示:
- 频繁在末尾追加行,外层切片扩容成本低
- 但在中间插入/删除行,需手动 copy,开销大
- 内层切片各自独立扩容,彼此不影响
容易被忽略的一点:二维切片的“行列”只是逻辑概念,底层没有任何连续内存保证。如果你需要真正连续的二维数据(比如图像像素),应该用一维切片 + 手动索引计算(data[y*width + x]),而不是嵌套切片。


















