Golang容器:切片

切片slice

动态分配大小连续的空间,切⽚是引⽤类型,当将⼀个切⽚赋值给另⼀个切⽚时,它们引⽤的是相同的底层数组。修改⼀个切⽚的元素会影响到其他引⽤该底层数组的切⽚。切⽚本身不存储元素,⽽是引⽤⼀个底层数组。切⽚的底层数组会在需要时进⾏动态扩展。

数据结构

go 复制代码
type slice struct {
    array unsafe.Pointer //指向底层数组的指针
    len   int //长度
    cap   int //容量
}

切片(slice)本身并非动态数组或数组指针。它内部通过指针引用底层数组,设定相关属性将数据读写操作限定在指定区域内。

go 复制代码
//切片声明定义
var s[] int
s:=make([]int,0)
//访问切片,i是切片下标,v是元素的值,可以通过i修改切片的值,不能通过v
for i,v:=range s{
	fmt.Println(v)
}
//添加元素
s:=append(s,5,5,5)
//复制
copy( dest Slice, src Slice []T) int

数据被追加到原底层数组。如超出cap限制,由于数组长度的不变性,当涉及底层数组大小无法满足要求时,会创建新的数组。切片容量的扩展是通过底层数组的重建来完成的。append()函数执行时,会首先将传入的切片参数复制一份,生成一个新的切片,

在 Go 1.18 之前的版本中,切片扩容遵循的策略是:对于容量小于 1024 个元素的切片,扩容时容量翻倍;而对于容量超过 1024 的切片,每次扩容增加现有容量的 25%,直至满足需求。

从 Go 1.18 版本开始,Go 语言对切片扩容策略进行了优化,以更高效地处理大容量切片的扩容问题,减少内存分配和拷贝的开销。优化后的扩容策略遵循以下原则:

  1. 容量增长:新容量至少等于原容量加上所需的额外空间,确保扩容满足需求。
  2. 高效内存分配:避免频繁的小幅度扩容,实现内存分配的高效性。

具体优化点包括:

  • 阈值调整:扩容策略的阈值从 1024 字节调整为 256 字节。当切片容量小于 256 字节时,容量增长速度为 2 倍;超过 256 字节后,增长速度减慢至 1.25 倍。
  • 扩容系数平滑过渡 :Go 1.18 引入了新的算法,使得在阈值附近扩容系数能够平滑过渡。具体算法为 (newcap + 3*threshold) / 4,其中 threshold 为 256 字节,这有助于避免扩容系数从 2 倍到 1.25 倍的突然变化。
  • 避免溢出:新策略还包括对潜在溢出的检查,确保在计算新容量时不会发生溢出,避免无限循环,并在必要时将新容量设置为请求的容量大小。
相关推荐
葫芦和十三2 小时前
图解 MongoDB 26|片键设计:决定集群命运的一个决定
后端·mongodb·agent
Avan_菜菜3 小时前
使用 Docker + rclone 自建 WebDAV
后端·agent·claude
阳光是sunny5 小时前
别再被 worktree 绕晕了!AI 编程时代你必须掌握的 Git 隔离神器
前端·人工智能·后端
万少6 小时前
万少的博客 - 技术分享与解决方案
前端·javascript·后端
咖啡八杯6 小时前
GoF设计模式——备忘录模式
java·后端·spring·设计模式
苍何6 小时前
腾讯再放大招,企微 Agent 大圆开启内测
后端
ethantan6 小时前
一篇讲解AI Agent 组成:像人一样思考的智能体
人工智能·后端·程序员
apocelipes8 小时前
常用编程语言和库的正则表达式性能对比
c语言·c++·python·性能优化·golang·开发工具和环境
Cosolar8 小时前
vLLM 生产级部署完全指南
人工智能·后端·架构
IT_陈寒9 小时前
垃圾回收器选错了,我的Java服务内存炸了
前端·人工智能·后端