前言
相信很多goher都知道slice在append时如果超出了原来的容量时会翻倍扩容。
疑问
这种翻倍扩容是可持续的吗?比如slice已经4GB了,这个时候难道会直接申请8GB?带着这个疑问我们直接去源码里找答案。
真相
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
26
27
28
|
// src/runtime/slice.go
// go version 1.13
func growslice(et *_type, old slice, cap int) slice {
// ...省略部分
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
//原切片长度低于1024时直接翻倍
if old.len < 1024 {
newcap = doublecap
} else {
// Check 0 < newcap to detect overflow
// and prevent an infinite loop.
//原切片长度大于等于1024时,每次只增加25%,直到满足需要的容量
for 0 < newcap && newcap < cap {
newcap += newcap / 4
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
if newcap <= 0 {
newcap = cap
}
}
}
// ...省略部分
}
|
源码里清楚的展示出了slice的长度在超过一个阈值(这里是1024)后便不再翻倍,而是每次以25%的幅度增长,直到满足所需的容量。