Go语言基础之切片!
Go语言基础之切片!
月伴飞鱼数组的局限:数组的长度是固定的,并且长度属于类型的一部分。
切片可以理解为长度可以动态变化的数组
- 它是基于数组类型做的一层封装,非常灵活,支持自动扩容。
切片(
Slice
)是一个拥有相同类型元素的可变长度的序列。切片是一个引用类型,它的内部结构包含
地址
、长度
和容量
。
- 切片一般用于快速地操作一块数据集合。
切片中可以容纳元素的个数称为容量,容量大于等于长度
- 可以通过
len(slice)
和cap(clice)
分别获取切片的长度和容量。可以通过
make(type,len,cap)
的方式创建出自动以初始长度和容量的切片
- 在追加元素的过程中,如果容量不够用时,就存在动态扩容问题
- 动态扩容采用的是倍增策略,即:
新容量=2*就容量
。扩容后的切片会得到一片新的连续内存地址,所有元素的地址都会随之发生改变。
切片的定义
1 | var name []T |
切片表达式
切片表达式从字符串、数组、指向数组或切片的指针构造字符串或切片,有两种变体:
- 一种指定start和end两个索引界限值得简单形式
- 另一种是除了start和end索引界限值外还制定容量的完整形式。
简单切片表达式:
切片的底层就是一个数组,可以基于数组通过切片表达式得到切片
- 切片中的
start
和end
表示一个索引范围(左包含,右不包含)
1 | func main(){ |
为了方便,通常可以省略切片表达式中的任何索引
- 省略了
start
则默认是0,省略了end
则默认到结尾。
1 | a[2:] // a[2:len(a)] |
完整切片表达式:
对于数组,指向数组的指针,或切片(注意不能是字符串)支持完整切片表达式。
1 | a[start:end:max] |
上面的代码会构造与简单切片表达式
a[start:end]
相同类型,相同长度和元素的切片
- 另外,它会将得到的结果切片的容量设置为
max-start
。在完整切片表达式中只有第一个索引值(start)可以省略,默认为0。
1 | func main(){ |
完整切片表达式需要满足的条件是
0<=start<=end<=max<=cap(a)
- 其他条件和简单切片表达式相同。
使用make()函数构造切片
上面都是基于数组来创建的切片
- 如果需要动态的创建哪一个切片,就需要使用内置函数
make()
1 | make([]T,size,cap) |
1 | func main(){ |
a
的内部存储空间已经分配了10个,但是实际上只用了2个,容量并不会影响当前元素的个数
- 所以
len(a)
返回2,cap(a)
则返回该切片的容量。
切片的本质
切片的本质就是对底层数组的封装,包含三个信息:
- 底层数组的指针,切片的长度和切片的容量。
现在有一个数组
a:=[8]int{0,1,2,3,4,5,6,7}
,切片s1:=a[:5]
相应的示意图如下:
切片
s2:=a[3:6]
,相应的示意图如下:
切片的赋值拷贝
拷贝前后两个变量共享底层数组
- 对一个切片的修改会影响另一个切片的内容。
1 | func main(){ |
切片的遍历
切片的遍历方式和数组是一致的,支持索引遍历和
for range
遍历。
1 | func main(){ |
向切片中添加元素
Go语言的内建函数
append()
可以为切片动态添加元素
- 可以一次添加一个元素,可以添加多个元素,也可以添加另外一个切片中的元素
1 | func main(){ |
通过var声明的零值切片可以在
append()
函数直接使用无需初始化。没有必要初始化一个切片再传入
append()
函数使用。
1 | s := []int{} // 没有必要初始化 |
从切片中删除元素
Go语言中并没有删除切片元素的专用方法,可以通过使用切片本身的特性来删除元素。
1 | func main(){ |
从切片a中删除索引为
index
的元素
- 操作方法是
a = append(a[:index], a[index+1:]...)