英文:
Confused about golang slice cap
问题
我对切片容量的问题有疑问,以下是代码:
var slice []int
list := []int{1,2,3,4,5}
for _,item := range list {
slice = append(slice, item)
}
fmt.Println(len(slice),cap(slice))
如果 item == 1
:len(slice)=1
,cap(slice)=1
如果 item == 2
:len(slice)=2
,cap(slice)=1*2
如果 item == 3
:len(slice)=3
,cap(slice)=2*2
如果 item == 4
:len(slice)=4
,cap(slice)=4
如果 item == 5
:len(slice)=5
,cap(slice)=4*2
所以输出结果为:
len(slice)=5
,cap(slice)=8
这没有问题,但当我改变代码如下:
var slice []int
slice = append(slice,1,2,3,4,5)
fmt.Println(len(slice),cap(slice))
输出结果为:
len(slice)=5
,cap(slice)=6
为什么 cap(slice)=6
?
英文:
i have a question about slice cap,the code:
var slice []int
list := []int{1,2,3,4,5}
for _,item := range list {
slice = append(slice, item)
}
fmt.Println(len(slice),cap(slice))
if item == 1: len(slice)=1,cap(slice)=1
if item == 2: len(slice)=2,cap(slice)= 1*2
if item ==3: len(slice) = 3,cap(slice) = 2*2
if item == 4:len(slice) = 4,cap(slice) = 4
if item == 5:len(slice) = 5,cap(slice) = 4*2
so the output:
len(slice) = 5,cap(slice) = 8
that's no problem,but when i change the code:
var slice []int
slice = append(slice,1,2,3,4,5)
fmt.Println(len(slice),cap(slice))
output:
len(slice) = 5,cap(slice) = 6
why cap(slice) = 6 ?
答案1
得分: 6
你可以在src/runtime/slice.go的func growslice(et *_type, old slice, cap int)
函数中看到在追加时进行容量计算的算法-第162行。
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
if old.cap < 1024 {
newcap = doublecap
} else {
// 检查 0 < newcap 以检测溢出并防止无限循环。
for 0 < newcap && newcap < cap {
newcap += newcap / 4
}
// 当新容量计算溢出时,将newcap设置为请求的容量。
if newcap <= 0 {
newcap = cap
}
}
}
> - 首先将旧切片的容量乘以2。如果乘以2后的容量仍然小于新切片的容量,则取新切片的容量(追加多个元素)。
> - 如果新切片小于旧切片容量的两倍,则将旧切片的容量乘以2。
> - 如果旧切片的容量大于或等于1024,则将新切片的容量乘以旧切片容量的1.25倍。
参考资料:
英文:
You can see the algorithm of capacity calculation when appending in func growslice(et *_type, old slice, cap int)
in src/runtime/slice.go - line 162
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
if old.cap < 1024 {
newcap = doublecap
} else {
// Check 0 < newcap to detect overflow
// and prevent an infinite loop.
for 0 < newcap && newcap < cap {
newcap += newcap / 4
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
if newcap <= 0 {
newcap = cap
}
}
}
> - First multiply the old slice capacity by 2. If the capacity after
> multiplying by 2 is still less than the new slice capacity, then take
> the new slice capacity (append multiple elems)
> - If the new slice is
> less than twice the old slice capacity, multiply the old slice
> capacity by 2
> - If the old slice capacity is greater than or equal to 1024, the new
> slice capacity is multiplied by the old slice capacity by 1.25
Reference -
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论