切片slice
- 切片是引用类型切片初始化之后才能进行使用
- 切片不能直接比较
append
函数可以向切片中追加元素,同时还能利用append
函数删除切片中的某个元素- 切片是数组的底层封装
make([]T, len,map)
函数能够直接创建切片make([]int, 5, 10)
切片(
Slice
)是一个拥有相同类型元素
的可变长度
的序列。切片是引用类型,必须初始化才能进行使用
。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。切片是一个引用类型,一般用于快速地操作一块数据集合。切片的底层就是数组,三要素:
- 地址:指针的第一个位置
- 长度:
len()
函数获得- 容量:
cap()
函数获得切片的基本语法:
1 | var name []T |
name
表示变量名T
:表示切片中的元素类型,比如string、int、bool
等- 切片创建的时候不指定长度;
[]
里面不带数字
1 | func main() { |
make函数
通过make()
函数构造动态的切片,基本语法为
1 | make([]T, size, cap) |
- T:切片的元素类型
- size:切片中元素的数量
- cap:切片的容量
1 | //make函数构造切片 |
切片的本质
切片的本质就是对底层数组的封装,它包含了三个信息:底层数组的指针、切片的长度(len)
和切片的容量(cap)
。
- 指针
- 长度
- 容量
现在有个数组a := [8]int{0, 1, 2, 3, 4, 5, 6, 7}
,切片s1 := a[:5]
,相应示意图如下:
- 指针:第一个元素所在的位置
- 长度:元素总个数
- 容量:原有数组的容量减去指针所在的位置
切片s2 := a[3:6]
切片不能直接比较
-
切片之间不能通过
==
来进行比较和判断 -
唯一合法的操作是和
nil
进行比较- 一个
nil
值的切片没有底层数组 nil
值的切片的长度和容量都是0- 不能说长度和容量是0的切片是
nil
- 一个
-
判断切片是否为空,用
len(s) == 0
1
2
3var s1 []int //len(s1)=0;cap(s1)=0;s1==nil
s2 := []int{} //len(s2)=0;cap(s2)=0;s2!=nil
s3 := make([]int, 0) //len(s3)=0;cap(s3)=0;s3!=nil
空切片nil
一个切片在未初始化之前默认都是nil
,长度是0
:
1 | package main |
切片赋值拷贝
当进行赋值拷贝之后,两个变量共享底层数组的数据,一个切片的变化会影响另一个切片。
1 | package main |
遍历
切片的遍历分为两种:索引遍历和for range
遍历
1 | package main |
append
append
函数可以为切片动态添加元素。每个切片指向一个底层数组,数组能够容纳一个数量的元素。当底层数组不能容纳新增的元素时,切片就会自动按照一定的策略进行“扩容”,此时该切片指向的底层数组就会更换。“扩容”操作往往发生在append()
函数调用时。
1 | package main |
1 | [0] len:1 cap:1 ptr:0xc00000e100 |
小结
- append函数将元素追加到切片的最后,同时需要原来的切片进行接收
- 容量按照1,2,4,8.16进行扩容,每次扩容后都是扩容前的2倍。
- append函数能够同时追加多个元素
切片的扩容策略
1 | newcap := old.cap |
copy函数
copy
函数实现将一个切片的数据迅速地复制到另一个切片空间中,切片要初始化之后才能使用。基本语法为:
1 | copy(destSlice, srcSlice []T) |
srcSlice
: 数据来源切片destSlice
: 目标切片
1 | package main |
总结:删除切片中索引为index的元素,需要注意的是append函数中可以同时追加多个元素
1 | append(a[0:index], a[index+1:]...) |
练习题
1 | package main |