go语言切片

什么是切片?

Go语言中的切片(slice)是一种方便且强大的数据结构,它可以让我们灵活地操作连续的元素序列,其实质是对数组的封装。

声明和初始化

Go语言中的切片可以使用以下语法声明:

var s []T

其中,T是切片所存储的元素类型,s是切片的变量名。

切片可以通过以下方式进行初始化:

  • 使用make()函数进行初始化
s := make([]T, length, capacity)

其中,T是切片所存储的元素类型,length是切片的长度,capacity是切片的容量。

  • 直接使用切片字面量进行初始化
s := []T{element1, element2, ..., elementN}

切片的基本操作

  • 获取切片长度:使用len()函数获取切片的长度。
  • 获取切片容量:使用cap()函数获取切片的容量。
  • 切片表达式:切片表达式用于从切片中获取一个子切片,语法为:
s[start:end]

其中,start表示子切片的起始索引(包含),end表示子切片的结束索引(不包含)。

  • 添加元素:使用内置函数append()将元素添加到切片末尾。
s = append(s, element)
  • 删除元素:可以通过切片表达式和append()函数将指定位置的元素删除。
s = append(s[:index], s[index+1:]...)

切片的内部结构

在Go语言中,切片是由三部分组成的,分别是指向底层数组的指针、切片的长度和切片的容量。这三部分通常被称为切片的头部(header)。

在Go语言中,一个切片的内部结构可以使用reflect.SliceHeader来表示,其中Data字段表示底层数组的指针,Len字段表示切片的长度,Cap字段表示切片的容量。

type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}

因为切片是一个动态的结构,因此我们可以将其看作一个由指针、长度和容量组成的指针类型。我们可以使用类型转换将一个指向数组的指针转换为一个切片的指针。

切片的长度和容量

在Go语言中,切片的长度和容量是两个不同的概念。切片的长度表示切片中元素的个数,而切片的容量表示底层数组中可以存储的元素的最大数量。

切片的长度可以通过内置函数len()来获取,切片的容量可以通过内置函数cap()来获取。

s := make([]int, 5, 10)
fmt.Println(len(s)) // 输出:5
fmt.Println(cap(s)) // 输出:10

在上面的代码中,我们创建了一个长度为5、容量为10的切片。由于切片的长度小于其容量,因此我们可以向切片中添加更多的元素,直到切片的长度等于其容量为止。

切片的扩容

当切片中的元素数量超过了其容量时,Go语言会自动扩容切片。切片的扩容机制是比较复杂的,它涉及到了内存分配、垃圾回收等方面的知识。

在Go语言中,切片的扩容机制是由运行时系统控制的。当我们使用append()函数向切片中添加元素时,Go语言会根据需要自动扩容切片。

切片的扩容机制大致分为以下两步:

  • 如果切片容量小于两倍的切片长度,则将切片容量扩大为两倍的切片长度。
  • 如果切片容量大于或等于两倍的切片长度,则将切片容量增加固定的量(通常是原始容量的25%),直到新容量大于等于所需容量为止。

切片的扩容机制可以帮助我们在使用切片时避免频繁地进行内存分配和拷贝操作

最后修改:2023 年 08 月 27 日
如果觉得我的文章对你有用,请随意赞赏