slice
简介
切片的数据结构可以抽象为以下3个变量:
一个指向原生数组的指针(ptr)
数组中的元素个数(len)
数组的大小(cap)
可以使用内置函数len(slice)
获取切片的元素个数,使用内置函数cap(slice)
获取切片的数组大小
声明语义
go语言的切片声明后不可直接使用,还需要进行赋值。声明后的零值为nil
:
var myslice []int
if myslice == nil {
fmt.Println("myslice is nil")
}
myslice = make([]int, 5, 10) // size: 5, cap: 10
for index, _ := range myslice {
myslice[index] = index
}
for _, value := range myslice {
fmt.Println(value)
}
初始化方法
直接定义与初始化
如下定义一个len和cap都为3的切片
slice := []int64{2, 4, 6}
使用make函数
slice1 := make([]int64, 5) // 创建一个len与cap都为5的切片,元素初始始化为0
slice2 := make([]int64, 5, 10) // 创建一个len为5,cap为10的切片,元素初始化为0
基于数组
array := [5]int64{2, 4, 6, 8, 10}
slice := array[3:] // (*)
这里需要详细说明一下(*)
这一行代码。这一行代码会创建一个切片,但切片的底层数组使用的是变量array,切片的指针是数组的第三个元素,也就是说该行代码并没有申请一个新的空间给切片元素;由于数组的大小为5,所以切片的len与cap都会初始化为3。
此时,当我们更改切片元素的值,数组的值也会相应变化。看如下代码与输出:
array := [5]int64{2, 4, 6, 8, 10}
slice := array[3:]
for i := 0; i < len(slice); i++ {
slice[i] = slice * 2
}
for i := 0; i < len(array); i++ {
fmt.Println(array[i])
}
输出如下:
2
4
12
16
20
当然,当我们继续往切片中添加元素,直到元素个数超出3个时,此时会为切片分配一个新的空间,这时修改切片的值就不会对原数组产生影响
遍历
len()
函数可以得到切片的长度,cap()
函数可以得到切片的空间。也可以用for ... range ...
来遍历切片
slice := []string{"one", "two", "three"}
for index, value := range arr {
fmt.Printf("index = %d, value = %s\n", index, value)
}
赋值
由于切片是一个内置类型,所以赋值操作与函数的参数传递都是go语言预定义好的。
赋值
切片的赋值相当于把右边切片的三个变量(prt、len、cap)赋值给左边切片,也就是说,赋值后两个切片使用的是同一个底层数组,且两个切片的len与cap也都一样。看下来的代码:
slice1 := []int64{1, 2, 3}
slice2 := []int64{4}
slice2 = slice1
slice2[0] = 5
fmt.Println(slice1)
fmt.Println(slice2)
输出:
[5 2 3]
[5 2 3]
当然,如果先赋值,再扩容,那么两个切片就不会相互影响,这是因为扩容后新的切片已经分配了新的内存空间,两个切片就不共享底层数组了,看如下代码:
slice1 := []int64{1, 2, 3}
slice2 := []int64{4}
slice2 = slice1
slice2 = append(slice2, 4, 5)
slice2[0] = 0
fmt.Println(slice1)
fmt.Println(slice2)
输出如下:
[1 2 3]
[0 2 3 4 5]
其他操作
添加元素
切片可以动态扩展,当cap - len
(即剩余空间)不足以容纳新元素的个数时,此时会重新分配一个新的空间,把原来空间的元素拷贝过来,然后再添加新的元素。
切片的动态扩展使用内置函数append()
,使用如下:
slice := []int64{1, 2, 3}
slice = append(slice, 4, 5) // 添加4,5两个元素
删除元素
Last updated
Was this helpful?