从数组中切出Slice
slice的切片操作arr[i:j],其中0 ≤ i≤ j≤ cap(arr),用于创建一个新的slice,
引用arr的从第i个元素开始到第j-1个元素的子序列(左闭右开区间)。
新的slice将只有j-i个元素。
如果i位置的索引被省略的话将使用0代替,如果j位置的索引被省略的话将使用len(arr)代替。
从切片中切出Slice
切片本身不存储元素,操纵的都是底层数组的
所谓的append()就是向底层数组中赋值
append()返回的是一个新的切片,这就是为什么必须要这么写 s = append(s, xx)
append()返回的新切片一定是从原数组上切出来的么?不一定。
综上,再看append()官方解释
切片的长度和容量怎么计算的?
一个slice是一个轻量级的数据结构,提供了访问数组子序列(或者全部)元素的功能,而且slice的底层确实引用一个数组对象。
一个切片是一个数组片段的描述。它包含了指向数组的指针,片段的长度, 和容量(片段的最大长度)。
内置的len和cap函数分别返回slice的长度和容量,长度不能超过容量。
指向数组的指针指向第一个slice元素对应的底层数组元素的地址
长度是切片目前引用的元素数目,对应slice中元素的数目
容量是切片能操控的底层数组的元素数目(从切片指针位置开始 ~ 底层数组的结尾位置)
增长超出切片容量将会导致运行时异常,就像切片或数组的索引超 出范围引起异常一样。
同样,不能使用小于零的索引去访问切片之前的元素。
make()函数创建切片
make([]T, len)
make([]T, len, cap) // same as make([]T, cap)[:len]
在底层,make创建了一个匿名的数组变量,然后返回一个slice;
只有通过返回的slice才能引用底层匿名的数组变量。
在第一种语句中,slice是整个数组的view。
在第二个语句中,slice只引用了底层数组的前len个元素,但是容量将包含整个的数组。
额外的元素是留给未来的增长用的。
切片 和 nil
slice唯一合法的比较操作是和nil比较
一个零值的slice等于nil。一个nil值的slice并没有底层数组。
一个nil值的slice的长度和容量都是0,但是也有非nil值的slice的长度和容量也是0的,例如[]int{}或make([]int, 3)[3:]。
与任意类型的nil值一样,我们可以用[]int(nil)类型转换表达式来生成一个对应类型slice的nil值。
如果你需要测试一个slice是否是空的,使用len(s) == 0来判断,而不应该用s == nil来判断。
除了和nil相等比较外,一个nil值的slice的行为和其它任意0长度的slice一样;
除了文档已经明确说明的地方,所有的Go语言函数应该以相同的方式对待nil值的slice和0长度的slice。