Go Slice
简介
切片是一种数据结构,这种数据结构便于使用和管理数据集合,围绕动态数组的概念构建,可以按需自动增长和缩小
内部实现
切片有三个字段,分别是指向底层数组的指针、切片的长度和切片的容量
创建和初始化
- Make
slice:=make([]string,5)
如果只指定长度,那么切片的容量和长度相等,也可以分别指定长度和容量
slice:=make([]string,3,5)
- 切片字面量
slice:=[]int{1,2,3}
可以设置长度和容量
slice:=[]string{99:""}
创建了长度和容量都是100个元素的切片
- nil切片
在声明时不做任何初始化,就会创建一个nil切片
var slice []int
想表示一个不存在的切片时
例如在函数要求返回一个切片但是发生异常的时候可以返回nil切片
- 声明空切片
slice:=make([]int,0)
slice2:=[]int{}
想表示空集合时空切片时
例如数据库查询返回零个结果时可以返回空切片
使用切片
- 赋值和切片
slice[0]=1
- 使用切片创建切片
slice:=[]int{10,20,30,40,50}
newSlice:=slice[1:3]
这时候我们有两个切片,他们共享同一段底层数组,如果一个切片修改了该底层数组的共享部分,另一个切片也能感知到
使用三个索引创建切片
允许限制新切片的容量为底层数组提供了一定的保护,可以更好地控制追加操作
- 切片增长
append
需要一个被操作的切片和一个要追加的值,它总会增加新切片的长度,而容量的变化取决于被操作的可用容量
slice:=[]int{10,20,30,40,50}
newSlice:=slice[1:3]
newSlice=append(newSlice,60)
由于newSlice
在底层数组里还有额外的容量可用,并且和原始的slice
共享同一个底层数组,因此索引为3
的元素的值也被改动了
如果在创建切片的时候设置的切片的长度和容量一样,就可以强制让新切片的第一个append
操作创建新的底层数组,与原有的底层数组分离,之后可以安全地进行后续修改
- 追加切片
s1:=[]int{1,2}
s2:=[]int{3,4}
fmt.Printf("%v",append(s1,s2...))
- 迭代切片
使用for range迭代切片
slice:=[]int{10,20,30,40}
for index,value:=range slice{
fmt.Printf("Index: %d Value: %d\n",index,value)
}
range
创建了每个元素的副本,而不是直接返回对该元素的引用,因此value的地址总是相同的
len()
函数返回切片或者映射的长度,cap()
函数只能返回切片的容量
若果使用传统for
循环进行迭代切片,可以使用len()
决定什么时候停止迭代
多维切片
- 声明多维切片
slice:=[][]int{{10},{100,200}}
- 组合切片的切片
slice:=[][]int{{10},{100,200}}
slice[0]=append(slice[0],20)
在函数间传递切片
由于切片的尺寸很小,在函数间复制和传递切片的成本也很低
slice:=make([]int,1e6)
slice=foo(slice)
func foo(slice []int)[]int{
...
return slice
}
在64位架构的机器上,一个切片需要24字节的内存,由于切片关联的数据包含在底层数组里,不属于切片本身,所以将切片复制到任何函数的时候,对底层数组大小都不会有影响