/ Go 语言多维切片完全攻略 /
切片是 Go 语言中一个非常重要也比较特殊的类型。除了基本的一维切片外,Go 语言还支持多维切片,即切片的元素也可以是切片。理解和应用多维切片对于提高 Go 语言编程能力非常关键。
本文将全面介绍 Go 语言多维切片相关的知识,包括:
- 二维切片基本介绍
- 多维切片声明
- 多维切片初始化
- 多维切片访问
- 从数组生成多维切片
- 不规则多维切片
- 多维切片的长度和容量
- 多维切片的复制
- 多维切片的遍历
- 多维切片的应用
对多维切片有全面的了解,可以帮助我们写出更灵活高效的 Go 语言代码。
1
1. 二维切片基本介绍
二维切片是最常见的多维切片,定于方式是[]Type。
可以把二维切片看成是一个切片的切片,每个内部切片的长度可以不同。这一点和二维数组不同,数组的每个内层长度必须相同。
举个例子,一个二维切片定义:
[][]int
访问第一个元素:
slice[0]
二维切片允许非统一长度,类似于链表。
2
2. 多维切片声明
下面是多维切片常见的声明方式:
var sl1 []int var sl2 [][]int var sl3 [][][]int
一维切片声明时只有一个[],二维三维类推,每个[]表示一层切片。
所以[][][]int就是一个三维int切片。
切片初始化时也可以用类似语法:
sl3 := [][][]int{}
3
3. 多维切片初始化
下面是多维切片初始化的各种方式:
// 空切片 var sl = [][]int{} // 使用make初始化,只设置长度 sl = make([][]int, 2) // 设置长度和容量 sl = make([][]int, 2, 4) // 含有元素的切片 sl = [][]int{{1,2},{3,4}} // 使用new初始化 sl = new([][]int)
make 可以指定长度和容量,用来初始化切片。
需要注意的是,多维切片每个内层切片的长度可以不同。
4
4. 多维切片访问
多维切片访问需要按层级顺序进行:
sl := [][]int{{1,2},{3},{4,5,6}} sl[0] // 获取第一层切片 sl[0][0] // 获取第二层的第一个元素 sl[1][0] // 第二层切片的第一个元素
切片索引从 0 开始,需要按顺序进行。
检查切片边界可以避免出错:
if len(sl) > i && len(sl[i]) > j { sl[i][j] }
5
5. 从数组生成多维切片
可以通过从数组切割来生成多维切片:
arr := [2][3]int{{1,2,3},{7,8,9}} sl := arr[:1][:2] // 获取二维切片 fmt.Println(sl) // [[1 2]]
需要按顺序切割获得多维切片。
这样可以构建不均匀长度的切片。
6
6. 不规则多维切片
举个不规则多维切片的例子:
sl := [][]int{ {1, 2, 3}, {4, 5}, {6}, }
不同内层切片长度不一样,这在多维切片中是允许的。
可以基于不规则切片构建特定的数据结构,比如链表。
需要注意切片边界,否则会导致访问错误。
7
7. 多维切片长度和容量
多维切片也有长度和容量的属性:
sl := [][]int{ {1, 2, 3}, {4, 5}, } len(sl) // 2,外层切片长度 cap(sl) // 2,外层切片容量 len(sl[0]) // 3,内层切片长度 cap(sl[0]) // 3,内层切片容量
内层切片长度可能不相同,但外层切片长度固定。
8
8. 多维切片的复制
多维切片之间进行复制也会复制外层和内存引用:
func main() { s1 := [][]int{{1}, {2}} s2 := make([][]int, 2) copy(s2, s1) s2[0][0] = 200 fmt.Println(s1) // [[200], [2]] }
可以看到 s1 也被修改了,因为两个切片引用同一内存。
需要深度复制每个内层切片的元素,而不是直接复制引用。
9
9. 多维切片的遍历
可以通过嵌套 for 循环来遍历多维切片:
for i := range sl { for j := range sl[i] { println(sl[i][j]) } }
或者使用 for range 代替内层 for:
for i := range sl { for j, v := range sl[i] { println(j, v) } }
这类似遍历二维数组,需要按层级顺序进行访问。
10
10. 多维切片应用
多维切片有很多实际的应用场景:
- 矩阵运算
- 嵌套数据结构
- 分层数据
- 树结构
- 网格结构
- 图像像素处理
例如可以用二维切片实现矩阵:
// 初始化一个二维矩阵 matrix := [][]float32{ {1, 2, 3}, {4, 5, 6}, } // 矩阵乘法 func mult(m1, m2 [][]float32) [][]float32 { // 矩阵乘法逻辑实现 ... }
再如表示分层或嵌套数据:
tree := [][]string{ {"root"}, {"first", "second"}, {"foo", "bar"}, }
多维切片非常灵活,可以表示多种复杂数据结构。
11
总结
通过本文全面讲解,可以深入理解 Go 语言多维切片的各方面知识,包括声明、初始化、访问、遍历等用法技巧。多维切片是一个非常强大的语言特性,可以实现各种嵌套和层次的数据结构。充分利用多维切片可以让我们的 Go 语言编程更加高效和富有表现力。