7.Go语言中的slice

Go语言中的slice,又称切片,比较类似动态数组,类似Java中的List,slice支持自动扩容,是常用的数据接口之一。

在了解slice之前,先介绍下,Go中的数组,数组是长度固定且类型相同的连续序列,有三个重要特征,(1)长度固定(2)元素类型相同(3)连续序列,长度相同和元素类型相同的2个数组可以称为这两个数组类型是一样的,连续序列指的是在内存中数组占用的是一段连续的内存。

Go中的数组是值类型的,所以在将数组传递进函数时,会发生值拷贝,即深拷贝一份数组给函数的形参,如果数据较大,会带来一定的性能问题,比较常见的做法是使用指针,在Go中更建议使用slice来代替数组的使用。

切片对于数组就像文件描述符对于文件,数组通常作为slice的底层存储存在,slice也可以看作是数组的窗口,使用slice屏蔽了底层数组的操作和扩容等,是非常常用的数据结构。

slice由三部分构成:(1)指向第一个元素的指针(2)长度(3)容量

这也就意味着slice是一个轻量级的,在传参时值拷贝也只是拷贝一个指针,slice的长度指的是开在数组上的窗口的大小,slice的容量指的是在底层数组上,从指针位置到数组末尾的大小。

下面的代码展示了切片的定义方式:(1)直接创建切片,runtime会在底层帮构建数组

(2)在已有的数组上切片化,切片上也可以切片化,此时会存在多个切片共享一个底层数组。

slice的自动扩容机制可以查看 $GOROOT/src/runtime/slice.go中的growslice函数

slice在自动扩容时会新建一个新的数组,然后将老数组的元素复制到新数组中,注意的是不会将老的slice指向这个新的数组,这和Java中的ArrayList的实现机制不同,所以在使用Go中的slice时,在append操作时,需要使用原有的slice变量接收下append的结果,否则发生自动扩容后,slice变量绑定的还是老的数组。

Go 复制代码
package main

import "fmt"

func main() {
	// 1 数组是固定长度 且 类型相同的连续序列
	// 因此 数组类型有2个属性:元素类型 和 数组长度
	// 只有 元素类型 和 长度 都相同的数组才能称之为同类型的数组
	// go语言的数组是值类型的,所以在传递数组到函数内时,发生的是值拷贝,如果数组比较大会有性能问题
	// 比较常见的做法是 将数组传递给函数的时候,传指针,但是在go中建议的做法是使用切片

	// 2 切片对于数组 就像 文件描述符对于文件
	// slice由三个结构构成,分别是 指针array 长度len 容量cap
	// array: 指向底层数组某元素的指针,该元素是切片的起始元素
	// len: 切片的长度,即切片中的元素个数
	// cap: 切片的最大容量

	// 3 直接创建切片,会在底层创建一个数组,数组的长度为5
	s := make([]byte, 5)
	fmt.Printf("s = %v\n", s)

	// 4 通过数组的 切片化 构造切片
	// 注意 当从一个数组上 切片化出多个切片时,切片对数组的修改是可能会影响其他切片的
	u := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	us1 := u[3:7]
	fmt.Printf("us1 = %v\n", us1)

	// 5 切片的动态扩容
	var s1 []int
	fmt.Printf("len = %v, cap = %v\n", len(s1), cap(s1)) // len = 0, cap = 0
	s1 = append(s1, 11)
	fmt.Printf("len = %v, cap = %v\n", len(s1), cap(s1)) // len = 1, cap = 4
	s1 = append(s1, 12)
	fmt.Printf("len = %v, cap = %v\n", len(s1), cap(s1)) // len = 2, cap = 4
	s1 = append(s1, 13)
	fmt.Printf("len = %v, cap = %v\n", len(s1), cap(s1)) // len = 3, cap = 4
	s1 = append(s1, 14)
	fmt.Printf("len = %v, cap = %v\n", len(s1), cap(s1)) // len = 4, cap = 4
	s1 = append(s1, 15)
	fmt.Printf("len = %v, cap = %v\n", len(s1), cap(s1)) // len = 5, cap = 8
}
相关推荐
第九序言T1 小时前
Python 数据处理进阶(十八)批量处理同结构文件:一个文件夹一次跑完
开发语言·python·自动化·pandas·数据处理
学长毕设2 小时前
基于springboot的食品仓库管理系统
java·spring boot·后端
滴滴答答哒2 小时前
ASP.NET Core + FaceRecognitionDotNet 人脸识别实战:DI 单例、特征向量持久化与 1:N 比对
后端·asp.net
龙亘川3 小时前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
程序喵大人3 小时前
【C++入门】内存模型与资源管理 - 09 shared_ptr 和 weak_ptr 解决共享,也带来代价
开发语言·c++·资源管理·智能指针·内存模型
Raas1003 小时前
AI网关部署方案?从部署到上线全流程
java·开发语言·人工智能·gateway·ai网关·企业级ai网关·企业级ai产品
专注仿真4 小时前
线性回归和逻辑回归算法详解
开发语言·人工智能·python·大模型训练·控制算法
jimy15 小时前
C++ 中的 `T&&`:右值引用与转发引用
开发语言·c++
captain3765 小时前
MyBatis操作数据库(入门2)
java·数据库·spring boot·后端·spring·mybatis
呆呆虫125 小时前
用 orjson 加速 SerpBase 响应解析:基准对比与注意事项
开发语言·php