slice的内部结构
一个slice本质上是一个数组的某个部分的引用。在go runtime/slice.go源码中定义了slice的结构:
type slice struct {
array unsafe.Pointer
len int
cap int
}
可以看到在Go的内部,slice是一个包含3个字段的结构体:
- array: 指向slice第一个元素的指针
- len: slice的长度,长度是索引操作的上届,
s[i] i<len(s)
- cap: slice的容量,容量是分割操作的上届,
s[i:j] j<=cap(s)
slice扩容
当对slice进行append的操作时,当容量不够时会引起slice的扩容:
func growslice(et *_type, old slice, cap int) slice {
......
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
if old.len < 1024 {
newcap = doublecap
} else {
for newcap < cap {
newcap += newcap / 4
}
}
}
......
return slice{p, old.len, newcap}
}
从以上源码可以看出在扩容时:
- 如果容量需求大于原cap的两倍以上,则扩容后容量即为需求的容量
- 否则: * 如果原来的len小于1024,则扩容后的cap为原cap的两倍。即按原cap 2倍增长扩容 * 如果原来的len大于等于1024,按1/4增长计算新的cap,直到满足容量需求。