
在 go 语言中,并没有传统意义上像 c++/c++ 那样严格的“多维数组”。相反,go 通过“切片的切片”(slice of slices)来模拟和实现多维数据结构的功能。例如,[][]uint8 并不是一个连续的内存块,而是一个包含 []uint8 类型元素的切片。这意味着它的每个元素本身又是一个 uint8 类型的切片。
这种设计使得 Go 语言的多维切片具有“锯齿状”(jagged)特性,即内部的各个切片(通常可以理解为“行”或“列”)可以拥有不同的长度,这与许多其他语言中严格矩形的多维数组有所不同。
make 是 Go 语言的一个内置函数,专门用于创建切片(slice)、映射(map)和通道(channel)。对于切片,make(T, len, cap) 会返回一个类型为 T、长度为 len、容量为 cap 的切片。如果省略 cap,则容量等于长度。
当 make 用于创建 [][]uint8 类型的切片时,例如 pic := make([][]uint8, dy),它会执行以下操作:
为了更直观地理解这一点,请看以下示例:
package main
import "fmt"
func main() {
// 创建一个长度为 2 的 [][]uint8 切片
ss := make([][]uint8, 2) // ss 的类型是 []([]uint8)
fmt.Printf("ss: %T %v 长度: %d\n", ss, ss, len(ss))
// 遍历 ss 的每个元素
for i, s := range ss { // s 的类型是 []uint8
fmt.Printf("ss[%d]: %T %v 长度: %d\n", i, s, s, len(s))
}
}输出:
ss: [][]uint8 [[] []] 长度: 2 ss[0]: []uint8 [] 长度: 0 ss[1]: []uint8 [] 长度: 0
从输出可以看出,尽管外部切片 ss 已经有了长度(2),但其内部的 []uint8 元素(即 ss[0] 和 ss[1])实际上都是未分配具体底层数组的空切片(nil 切片),它们的长度都为 0。这意味着此时你不能直接对 ss[0][0] 进行赋值操作,因为 ss[0] 还没有实际的存储空间。
正是因为 make([][]uint8, dy) 仅仅分配了外部切片,并将其内部元素初始化为 nil 切片,所以我们需要第二次 make 调用来为每个内部切片分配实际的底层数组。
第一次 make (pic := make([][]uint8, dy)): 这一步创建了 dy 个“容器”,每个容器准备好存放一个 []uint8 类型的切片。此时这些容器是空的(nil)。你可以将其想象成一个有 dy 行的表格,但每行都还是空的,没有具体的列。
第二次 make (pic[i] = make([]uint8, dx)): 在一个循环中,对 pic 的每个元素(即每个“容器”)进行操作。pic[i] = make([]uint8, dx) 实际为第 i 个内部切片分配了一个长度为 dx 的 uint8 数组,并将其引用赋值给 pic[i]。至此,这个内部切片才真正有了存储数据的空间,可以进行读写操作。这就像你为表格的每一行填充了具体数量的列。
这种分步初始化是 Go 语言切片设计哲学的一部分,它提供了极大的灵活性,允许创建非矩形的、锯齿状的多维结构。
以下是一个典型的 Go 语言中初始化二维切片的函数示例,它清晰地展示了两次 make 的作用:
func Pic(dx, dy int) [][]uint8 {
// 第一次 make: 分配外部切片,长度为 dy。
// 此时 pic 包含 dy 个 nil 的 []uint8 切片。
// 它只创建了“行”的引用,但每行还没有实际的“列”数据空间。
pic := make([][]uint8, dy)
// 遍历外部切片的每个元素(即每一行)
for i := range pic {
// 第二次 make: 为 pic[i] (即每个内部切片/每一行) 分配具体的 []uint8 空间,长度为 dx。
// 此时 pic[i] 才真正有了底层数组来存储 uint8 数据。
// 这一步为每一行创建了具体的“列”数据空间。
pic[i] = make([]uint8, dx)
// 填充数据:遍历当前行的每个元素
for j := range pic[i] {
// 对每个 uint8 元素进行赋值操作
pic[i][j] = uint8((i + j) / 2)
}
}
return pic
}这段代码清晰地展示了两次 make 的作用:第一次构建了外部切片的骨架(定义了有多少行),第二次在循环中为骨架中的每一行分配了具体的存储空间(定义了每行有多少列)。
以上就是深入理解 Go 语言多维切片的初始化与结构的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号