18版本后) _

本文由 简悦 SimpRead 转码, 原文地址 www.cnblogs.com 合集 - golang(4)1.Go 语言中 List 基本用法与源码详解 2023-05-142.golang slice (切片) 扩容机制详解(1.18 版本后)2023-07-193.Golang - Slice 学习笔记 2023-08-224.Go 语言中闭包与 defer2023-09-09收起

slice 源码定义

1
2
3
4
5
type slice struct {
array unsafe.Pointer //指向底层数组的指针
len int //切片长度
cap int //切片容量
}

growslice() 方法:用于 slice 的扩容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
func growslice(et *_type, old slice, cap int) slice {
// ......
newcap := old.cap
doublecap := newcap + newcap //双倍扩容(原容量的两倍)
if cap > doublecap { //如果所需容量大于 两倍扩容,则直接扩容到所需容量
newcap = cap
} else {
const threshold = 256 //这里设置了一个 阈值 -- 256
if old.cap < threshold { //如果旧容量 小于 256,则两倍扩容
newcap = doublecap
} else {
// 检查 0 < newcap 以检测溢出并防止无限循环。
for 0 < newcap && newcap < cap { //如果新容量 > 0 并且 原容量 小于 所需容量

// 从小片的增长2x过渡到大片的增长1.25x。这个公式给出了两者之间的平滑过渡。(这里的系数会随着容量的大小发生变化,从2.0到无线接近1.25)
newcap += (newcap + 3*threshold) / 4


//当newcap计算溢出时,将newcap设置为请求的上限。
if newcap <= 0 { // 如果发生了溢出,将新容量设置为请求的容量大小
newcap = cap
}
}
}
}

具体情况如下:

  1. 如果请求容量 大于 两倍现有容量 ,则新容量 直接为请求容量

  2. 否则(请求容量 小于等于 两倍现有容量)

​ 如果 现有容量 小于 256 ,则新容量是原来的两倍

​ 否则:新容量 = 1.25 原容量 + 3/4 阈值 “这个公式给出了从 1.25 倍增长 过渡到 2 倍增长,两者之间的平滑过渡。” 在此情况下,如果发生了溢出,将新容量设置为请求的容量大小

注意:目前仍然存在追加顺序的问题:当前切片的扩容,严格依赖第一个切片的容量,以第一个切片的容量进行计算,如果交换两个切片,两种方式得到的新切片的容量大概率是不一样的

EOF

* 本文作者: 小星 Code-go

作者

JIeJaitt

发布于

2025-01-29

更新于

2025-01-29

许可协议

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×