golang中切片擴容後的大小問題

2021-09-25 15:35:56 字數 1825 閱讀 9791

眾所周知,golang中切片在容量不足時會自動擴容,那麼擴容後的切片容量到底是多少呢?

瀏覽了很多文章,絕大多數給出的答案都是小於1024時為原來的2倍,大於1024時是1.25倍,因為原始碼中這樣一段**

// src/runtime/slice.go:100

newcap := old.

cap doublecap := newcap + newcap

ifcap

> doublecap

else

else

}}

看上去的確是這樣,但是,newcaps的計算並沒有結束,所以,上面的說法嚴謹的來說是錯誤的。

newcaps在進行了翻倍或者是增加25%後,還會進行接下來的計算

// src/runtime/slice.go:82

func

growslice

(et *_type, old slice,

capint

) slice

// ......

}

et代表slice中的元素型別,old是擴容前的切片,cap是擴容後的至少需要的最小容量,即old.caps + 本次新增的元素數量,ptrsize是指乙個指標的大小,在64位中為8。到這裡後會根據et.size的大小進入roundupsize去調整newcaps的大小。當入參小於32768時,主要依賴class_to_size,size_to_class8或size_to_class128這三個陣列中的兩個去調整newcaps。

// src/runtime/msize.go:35

func

roundupsize

(size uintptr

)uintptr

else

}// _pagesize = 1 << 13

if size+_pagesize < size

return

round

(size, _pagesize)

}

// src/runtime/stubs.go:289

func

round

(n, a uintptr

)uintptr

var size_to_class8 =

[smallsizemax/smallsizediv +1]

uint8

var size_to_class128 =

[(_maxsmallsize-smallsizemax)

/largesizediv +1]

uint8

var class_to_size =

[_numsizeclasses]

uint16

舉個例子:

package main

import

"fmt"

func

main()

s =(s,4,5

,6) fmt.

printf

("len=%d, cap=%d"

,len

(s),

cap(s)

)}

最後得到的結果為

len=5, cap=6
newcap =

int(capmem / et.size)

Go 中切片擴容的策略

如果切片的容量小於 1024 個元素,於是擴容的時候就翻倍增加容量。上面那個例子也驗證了這一情況,總容量從原來的4個翻倍到現在的8個。一旦元素個數超過 1024 個元素,那麼增長因子就變成 1.25 即每次增加原來容量的四分之一。注意 擴容擴大的容量都是針對原來的容量而言的,而不是針對原來陣列的長度...

golang中切片 slice 的坑

golang中陣列的長度是不可以變得,但是某些場合就不使用了,go提供了一種靈活,功能強悍的型別 切片,切片中有兩種概念 一種是len長度,二是cap容量,長度是已經被賦值的最大下標 1,可以通過len函式獲得切片的長度。容量是指切片最大可容納多少個元素,可以通過cap函式獲得,切片是引用型別,因此...

golang中slice的擴容機制

在golang中slice是乙個指向陣列的指標結構體。這個結構體有三個屬性 其概念為 動態陣列 及陣列的容量大小 cap 會隨著陣列的實際大小 size 變化而變化 擴容 擴容機制 如果切片的容量小於1024個元素,那麼擴容的時候slice的cap就翻番,乘以2 一旦元素個數超過1024個元素,則乘...