文章目录
切片(slice)是 Golang 中一种比较特殊的数据结构,这种数据结构更便于使用和管理数据集合。切片是围绕动态数组的概念构建的,可以按需自动增长和缩小。切片的动态增长是通过内置函数 append() 来实现的,这个函数可以快速且高效地增长切片,也可以通过对切片再次切割,缩小一个切片的大小。因为切片的底层也是在连续的内存块中分配的,所以切片还能获得索引、迭代以及为垃圾回收优化的好处。
1.切片的内部实现
切片是一个很小的对象,它对底层的数组(内部是通过数组保存数据的)进行了抽象,并提供相关的操作方法。切片是一个有三个字段的数据结构,这些数据结构包含 Golang 需要操作底层数组的元数据:
这 3 个字段分别是指向底层数组的指针、切片访问的元素的个数(即长度)和切片允许增长到的元素个数(即容量)。
2.切片的创建和初始化
在 Golang 中可以通过多种方式创建和初始化切片。是否提前知道切片所需的容量通常会决定如何创建切片。
通过 make() 函数创建切片
使用 Golang 内置的 make() 函数创建切片,此时需要传入一个参数来指定切片的长度:
// 创建一个整型切片
// 其长度和容量都是 5 个元素
slice := make([]int, 5)
此时只指定了切片的长度,那么切片的容量和长度相等。也可以分别指定长度和容量:
// 创建一个整型切片
// 其长度为 3 个元素,容量为 5 个元素
slice := make([]int, 3, 5)
分别指定长度和容量时,创建的切片,底层数组的长度是指定的容量,但是初始化后并不能访问所有的数组元素。
注意,Golang 不允许创建容量小于长度的切片,当创建的切片容量小于长度时会在编译时刻报错:
// 创建一个整型切片
// 使其长度大于容量
myNum := make([]int, 5, 3)
编译上面的代码,会收到下面的编译错误:
len larger than cap in make([]int)
通过字面量创建切片
另一种常用的创建切片的方法是使用切片字面量,这种方法和创建数组类似,只是不需要指定[]运算符里的值。初始的长度和容量会基于初始化时提供的元素的个数确定:
// 创建字符串切片
// 其长度和容量都是 3 个元素
myStr := []string{
"Jack", "Mark", "Nick"}
// 创建一个整型切片
// 其长度和容量都是 4 个元素
myNum := []int{
10, 20, 30, 40}
当使用切片字面量创建切片时,还可以设置初始长度和容量。要做的就是在初始化时给出所需的长度和容量作为索引。下面的语法展示了如何使用索引方式创建长度和容量都是100个元素的切片:
// 创建字符串切片
// 使用空字符串初始化第 100 个元素
myStr := []string{
99: ""}
区分数组的声明和切片的声明方式
当使用字面量来声明切片时,其语法与使用字面量声明数组非常相似。二者的区别是:如果在 [] 运算符里指定了一个值,那么创建的就是数组而不是切片。只有在 [] 中不指定值的时候,创建的才是切片。看下面的例子:
// 创建有 3 个元素的整型数组
myArray := [3]int{
10, 20, 30}
// 创建长度和容量都是 3 的整型切片
mySlice := []int{
10, 20, 30<