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的切片

  • 使用make函数

  • 基于数组

这里需要详细说明一下(*)这一行代码。这一行代码会创建一个切片,但切片的底层数组使用的是变量array,切片的指针是数组的第三个元素,也就是说该行代码并没有申请一个新的空间给切片元素;由于数组的大小为5,所以切片的len与cap都会初始化为3。

此时,当我们更改切片元素的值,数组的值也会相应变化。看如下代码与输出:

输出如下:

当然,当我们继续往切片中添加元素,直到元素个数超出3个时,此时会为切片分配一个新的空间,这时修改切片的值就不会对原数组产生影响

遍历

len()函数可以得到切片的长度,cap()函数可以得到切片的空间。也可以用for ... range ...来遍历切片

赋值

由于切片是一个内置类型,所以赋值操作与函数的参数传递都是go语言预定义好的。

  • 赋值

切片的赋值相当于把右边切片的三个变量(prt、len、cap)赋值给左边切片,也就是说,赋值后两个切片使用的是同一个底层数组,且两个切片的len与cap也都一样。看下来的代码:

输出:

当然,如果先赋值,再扩容,那么两个切片就不会相互影响,这是因为扩容后新的切片已经分配了新的内存空间,两个切片就不共享底层数组了,看如下代码:

输出如下:

其他操作

  • 添加元素

切片可以动态扩展,当cap - len(即剩余空间)不足以容纳新元素的个数时,此时会重新分配一个新的空间,把原来空间的元素拷贝过来,然后再添加新的元素。

切片的动态扩展使用内置函数append(),使用如下:

  • 删除元素

Last updated

Was this helpful?