对golang切片帽的困惑

xxd*_*pac 0 go slice

我有一个关于切片帽的问题,代码:

var slice []int
list := []int{1,2,3,4,5}
for _,item := range list {
    slice = append(slice, item)
}
fmt.Println(len(slice),cap(slice))
Run Code Online (Sandbox Code Playgroud)

如果 item == 1: len(slice)=1,cap(slice)=1

如果 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

所以输出:

len(slice) = 5,cap(slice) = 8

那没问题,但是当我更改代码时:

var slice []int
slice = append(slice,1,2,3,4,5)
fmt.Println(len(slice),cap(slice))
Run Code Online (Sandbox Code Playgroud)

输出:

len(slice) = 5,cap(slice) = 6

为什么 cap(slice) = 6 ?

nip*_*una 6

func growslice(et *_type, old slice, cap int)src/runtime/slice.go中追加时可以看到容量计算的算法-第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
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)
  • 先将旧切片容量乘以2,如果乘以2后容量仍小于新切片容量,则取新切片容量(追加多个elems)
  • 如果新切片小于旧切片容量的两倍,则将旧切片容量乘以 2
  • 如果旧分片容量大于等于1024,则新分片容量乘以旧分片容量乘以1.25

参考 -