Golang切片的底层实现原理

本文深入探讨了Golang切片的底层实现,包括切片的定义、动态扩容、拷贝以及线程安全性。通过示例代码展示了切片如何基于数组创建,以及切片拷贝的浅拷贝与深拷贝区别。文章强调了预估切片容量以减少动态扩容带来的性能损耗,并指出并发写入切片时需要注意线程安全问题。
摘要由CSDN通过智能技术生成

切片究竟是什么

我们的宗旨是『知其然也必知其所以然』,说切片之前,不得不说一句go语言的数组,数组是一个固定长度的、容纳同类型元素的连续序列,比如,var a [8]int 就是定义了一个长度为8,类型为int类型的数组。

在Go语言中传递数组是纯粹的值拷贝,对于元素类型长度较大或元素个数较多的数组,如果直接以数组类型参数传递到函数中会有不小的性能损耗。有同学可能说我可以用数组指针类型做形参,对数组变量取地址传进去,可以吗?可以,能避免性能消耗,但是不如切片好使,继续往下看,带你知其所以然。

切片之于数组就像是文件描述符之于文件。数组退居幕后,承担起底层存储空间,而切片走向前台,给开发者一个更便捷使用数组的窗口。打开 GOROOT/src/runtime/slice.go,可以看到切片的类型定义:

看到切片的数据结构包含3个字段:

array:指向下层数组的指针;不用着急知道这个指针指向哪,后边验证代码中就知道了

len:切片的长度,即切片中当前元素的个数,即内置函数len()返回的值

cap:切片的最大容量,即内置函数cap()返回的值,cap >= len

所以,每个切片变量都是一个runtime.slice结构体类型的实例,接下来我们通过日常定义切片的集中方式,来慢慢揭开这个结构体的真身,尤其是数组指针。

定义切片的几种方式

数组的切片化 [low:high]

定义一个数组,a := [10]int {11,12,13,14,15,16,17,18,19,20}

通过数组定义切片,s := a[3:7]

此时,数组和切片的内存布局是这样的:

『知其然也必知其所以然』,是我们的宗旨,上代码:

既然说切片复用的数组的存储空间,那我们把切片结构中的数组指针以及指向数组的元素a[3]地址打出来看看,并通过切片来修改元素

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知其然也必知其所以然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值