Go语言切片详解

简介: Go语言切片详解

1 前言


去年校招入职字节跳动从Java转Go已经有大半年了,说实话Go上手还是很容易的,而我期间一直在写业务相关的需求,对Go的一些底层数据结构的了解还是不够深入的,难得春节假期放长假,那么就以博客的形式来记录下Go数据结构的学习吧


2 切片简介


切片是一种数据结构,这种数据结构便于使用和管理数据集合。切片是围绕动态数组的概念构建的,可以按需自动增长和缩小。切片的动态增长是通过内置函数 append 来实现的。这个函数可以快速且高效地增长切片。还可以通过对切片再次切片来缩小一个切片的大小。因为切片的底层内存也是在连续块中分配的,所以切片还能获得索引、迭代以及为垃圾回收优化的好处。


3 切片的数据结构


切片本身并不是动态数组或者数组指针。它内部实现的数据结构通过指针引用底层数组,设定相关属性将数据读写操作限定在指定的区域内。切片本身是一个只读对象,其工作机制类似数组指针的一种封装。


切片(slice)是对数组一个连续片段的引用,所以切片是一个引用类型。这个片段可以是整个数组,或者是由起始和终止索引标识的一些项的子集。需要注意的是,终止索引标识的项不包括在切片内。切片提供了一个与指向数组的动态窗口。


给定项的切片索引可能比相关数组的相同元素的索引小。和数组不同的是,切片的长度可以在运行时修改,最小为 0 最大为相关数组的长度:切片是一个长度可变的数组。


Slice 的数据结构定义如下:

type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

可见slice结构体由三部分组成:


  • array 表示一个指向数组的指针
  • len 表示切片的长度
  • cap 表示切片的最大容量


简单了解了切片的数据结构后,我们来看看切片初始化的几种方式,后续还会对切片的内部实现做更近深入的介绍。


4 切片初始化的几种方式


Go中有几种方法可以创建和初始化切片。是否能提前知道切片需要的容量通常会决定要如何创建切片。


3.1 nil 切片


var slice []int64


在Go里,nil 切片是很常见的创建切片的方法,Go不会为nil切片分配任何空间。


284a4ad94bf74f768e7e0136acb608db.png


3.2 空切片


// 使用 make 创建空的整型切片
slice := make([]int, 0)
// 使用切片字面量创建空的整型切片
slice := []int{}


在Go里,空切片在底层数组包含 0个元素,也没有分配任何存储空间。

6dcb04af00fe4a13abaa6ee8b468b39c.png


不管是使用 nil 切片还是空切片,对其调用内置函数 append、len 和 cap 的返回结果都是一样的。


3.3 nil 切片与空切片的区别


由上面两个示意图可以知道,空切片和 nil 切片的区别在于,空切片指向的地址不是nil,指向的是一个内存地址,但是它也没有分配任何内存空间,即底层数组中包含0个元素。


3.4 make和切片字面量


一种创建切片的方法是使用内置的 make 函数。当使用 make 时,需要传入一个参数,指定切片的长度:

// 创建一个字符串切片
// 其长度和容量都是5个元素
slice := make([]string, 5)

如果只指定长度,那么切片的容量和长度相等。也可以分别指定长度和容量:

// 创建一个整型切片
// 其长度为 3 个元素,容量为 5 个元素 
slice := make([]int, 3, 5)


分别指定长度和容量时,创建的切片,底层数组的长度是指定的容量,但是初始化后并不能访问所有的数组元素。切片可以访问 3 个元素,而底层数组拥有 5 个元素。剩余的 2 个元素可以在后期操作中合并到切片,可以通过切片访问这些元素。如果基于这个切片创建新的切片,新切片会和原有切片共享底层数组,也能通过后期操作来访问多余容量的元素。


不允许创建容量小于长度的切片:

// 创建一个整型切片
// 使其长度大于容量
slice := make([]int, 5, 3)
// Compiler Error:
// len larger than cap in make([]int)

另一种常用的创建切片的方法是使用切片字面量,这种方法和创建数组类似,只是不需要指定[]运算符里的值。初始的长度和容量会基于初始化时提供的元素的个数确定。


// 创建一个整型切片
// 其长度和容量都是 3 个元素 
slice := []int{10, 20, 30}


相关文章
|
13天前
|
存储 Go 索引
go语言中数组和切片
go语言中数组和切片
25 7
|
12天前
|
Go 开发工具
百炼-千问模型通过openai接口构建assistant 等 go语言
由于阿里百炼平台通义千问大模型没有完善的go语言兼容openapi示例,并且官方答复assistant是不兼容openapi sdk的。 实际使用中发现是能够支持的,所以自己写了一个demo test示例,给大家做一个参考。
|
13天前
|
程序员 Go
go语言中结构体(Struct)
go语言中结构体(Struct)
90 71
|
12天前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
97 67
|
15天前
|
Go 索引
go语言for遍历数组或切片
go语言for遍历数组或切片
86 62
|
13天前
|
存储 Go
go语言中映射
go语言中映射
30 11
|
15天前
|
Go
go语言for遍历映射(map)
go语言for遍历映射(map)
28 12
|
14天前
|
Go 索引
go语言使用索引遍历
go语言使用索引遍历
24 9
|
14天前
|
Go 索引
go语言使用range关键字
go语言使用range关键字
23 7
|
15天前
|
Go
go语言for 遍历字符串
go语言for 遍历字符串
25 8