Go语言——Slice分析
源码很不好找,在go\src\runtime\slice.go。
type slice struct {
array unsafe.Pointer
len int
cap int
}
func makeslice(et *_type, len, cap int) slice {
p := mallocgc(et.size*uintptr(cap), et, true)
return slice{p, len, cap}
}
根据容量cap*元素size,申请一块内存。mallocgc
大空间(大于32kb)才会在heap堆上申请,否则在栈上分配,具体以后再介绍。
这里我们就看到切片底层就是数组,特别的是切片可以增长。
grow
注释
// it returns a new slice with at least that capacity, with the old data
// copied into it.
// The new slice's length is set to the old slice's length,
// NOT to the new requested capacity.
// This is for codegen convenience. The old slice's length is used immediately
// to calculate where to write new values during an append.
Note:
- 方法返回的新切片容量至少达到请求,也就是说新的容量可能比申请的多;
- copy老数据,也就是说有性能损耗;
- len一致,因为数据内容不变.
cap
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
}
}
}
cap增长策略:
- 如果期望大于double,新cap就等于期望;
- 如果当前大小小于1024,则两倍增长;
- 否则每次增长25%,直到满足期望。
网友评论