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 倍的突然变化。
  • 避免溢出:新策略还包括对潜在溢出的检查,确保在计算新容量时不会发生溢出,避免无限循环,并在必要时将新容量设置为请求的容量大小。
相关推荐
GetcharZp2 小时前
玩转 Linux 机器视觉:手把手带你搞定 Ubuntu 下海康工业相机 C++ SDK
后端
星星在线5 小时前
MusicFree:一个「All in One」的个人音乐服务器,让听歌回归简单
前端·后端
IT_陈寒6 小时前
Redis的SETNX并发问题让我加了三天班
前端·人工智能·后端
demo007x6 小时前
Docling 文档转换以及技术架构分析
前端·后端·程序员
袋鱼不重8 小时前
我的神奇同事,AI 用多了居然写了个 Open In Codex
前端·后端·ai编程
用户8356290780518 小时前
使用 Python 操作 Word 内容控件
后端·python
像我这样帅的人丶你还8 小时前
啥? 前端也要会干Java?🛵🛵🛵
后端
Hommy888 小时前
【剪映小助手】添加贴纸接口(Add Sticker)
后端·github·剪映小助手·视频剪辑自动化·剪映api
LDR0068 小时前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术8 小时前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript