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}


相关文章
|
7天前
|
安全 网络协议 Go
Go语言网络编程
【10月更文挑战第28天】Go语言网络编程
96 65
|
2天前
|
JavaScript Java Go
探索Go语言在微服务架构中的优势
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出。本文将深入探讨Go语言在构建微服务时的性能优势,包括其在内存管理、网络编程、并发模型以及工具链支持方面的特点。通过对比其他流行语言,我们将揭示Go语言如何成为微服务架构中的一股清流。
|
7天前
|
网络协议 安全 Go
Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
【10月更文挑战第28天】Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
32 13
|
2天前
|
SQL 关系型数据库 MySQL
go语言中安装数据库驱动
【11月更文挑战第1天】
15 5
|
2天前
|
编译器 Go 开发者
go语言中导入相关包
【11月更文挑战第1天】
10 3
|
3天前
|
测试技术 Go
go语言中测试工具
【10月更文挑战第22天】
13 4
|
3天前
|
SQL 关系型数据库 MySQL
go语言中数据库操作
【10月更文挑战第22天】
14 4
|
3天前
|
缓存 前端开发 中间件
go语言中Web框架
【10月更文挑战第22天】
14 4
|
2天前
|
关系型数据库 MySQL 数据库连接
go语言中打开数据库连接
【11月更文挑战第1天】
12 2
|
7天前
|
网络协议 安全 Go
Go语言的网络编程基础
【10月更文挑战第28天】Go语言的网络编程基础
25 8