第一次接触Go,发现语法中最让我感兴趣的莫过于其中切片操作,起初只是把它当成C++中的vector去使用,但是深入学习下来,发现两者还是有很大区别,用这篇文章来记录一下切片的一些特性。
Go数组
Go的数组和其他语言的数组区别不大,都需要预先指定数组的大小,一旦指定,则无法改变,因为长度是数组类型的一部分,不同长度的数组是不同的类型([4]int和[5]int不同)。
类型 [n]T 表示拥有 n 个 T 类型的值的数组。创建方法如下:
// 数组的创建方法
var arr [2]int
var arr [...]int{1, 2} // 自动推断长度
需要注意的是Go的数组是值语义。一个数组变量表示整个数组,它不是指向第一个元素的指针(不像 C 语言的数组)。 当一个数组变量被赋值或者被传递的时候,实际上会复制整个数组。
切片
一个切片是一个数组片段的描述。它包含了指向数组的指针,片段的长度和容量。长度是切片引用的元素数目。容量是底层数组的元素数目(从切片指针开始)。
切片操作并不复制切片指向的元素。它创建一个新的切片并复用原来切片的底层数组,也就是说通过一个新切片修改元素会影响到原始切片的对应元素。
类型 []T 表示一个元素类型为 T 的切片。切片创建方法如下:
// 切片的创建方法
slice := arr[:] // 针对数组arr的切片
slice := arr[0 : 1] //使用索引创造部分切片
slice := make([]int, 2) // 创建一个长度为2的切片
长度和容量
前面提到了关于长度和容量的说明。下面通过一个例子来更好说明其含义。
首先通过s := make([]int, 5)来创建一个长度为5的切片s。
继续对其进行切片s = s[2:4]观察其底层数组形态。
接着我们对其进行增长s = s[:cap(s)]。
这里需要注意切片的增长不能超过其容量,否则会导致运行时异常。