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 倍的突然变化。
  • 避免溢出:新策略还包括对潜在溢出的检查,确保在计算新容量时不会发生溢出,避免无限循环,并在必要时将新容量设置为请求的容量大小。
相关推荐
逝水无殇几秒前
C# 反射详解
开发语言·后端·c#
Cache技术分享5 分钟前
465. Java 反射 - 获取类的简单名
前端·后端
做系统的大强10 分钟前
REPL里的HLT:main_stmts为空时的致命尾声
后端
xlxxy_16 分钟前
sap获取批次特性报表
java·linux·开发语言·前端·数据库·abap·mm
薛定谔的悦16 分钟前
光伏-储能-负荷联合预测:给 EMS 装上"预知能力"
后端
云技纵横16 分钟前
Redis 延迟双删还是读到脏数据?一次缓存一致性事故
redis·后端·面试
北冥you鱼17 分钟前
Go语言常用包使用指南:从标准库到第三方利器
开发语言·microsoft·golang
网易云信23 分钟前
从“合规”到“信任”:网易智企专属云打造强监管下的通信新范式
人工智能·后端
俺不中嘞26 分钟前
python常用函数
开发语言·python
欢喜躲在眉梢里34 分钟前
用飞算Java做了一套新能源充电运营管理系统:把站点、设备、订单拆成可运营的微服务
java·开发语言·微服务·ai编程·技术分享·java开发·飞算javaai炫技赛