golang的切片 capacity 有意義嗎? 不是動態擴縮嗎?需要關注這個引數嗎?
slice
是個
fat array
,正是因為它有
len
和
cap
屬性才能實現動態擴縮。
len
是已使用的長度,
cap
是容量。
假如沒有
cap
,只有
len
,怎麼知道是否需要擴容呢?
但是一般都不怎麼需要關注
cap
。
特殊場景比如
bytebufferpool
會關注
cap
的大小。
這個主要是為了一個預分配機制。假設以下程式碼:
for i:=0;i<100;i++{
slice = append(slice,i)
}
你看到這個陣列在append的過程中會涉及到100次的記憶體分配,那是很大的消耗了。
所以如果在已知的情況下,比如你知道你這個slice最大不會超過200,那麼可以提前設定cap的值為200,一次分配記憶體。
在未知的情況下,go也會自動的幫你多分配一些記憶體給你。這樣不用你每次修改slice長度都涉及到分配/歸還記憶體操作。
如果剛開始就知道slice預計的最大長度,當然是把容量定義成這個值左右效能高。
例如slice最終長度是1000,初始容量定為1
就需要經過2,4,8,16,32,64,128,256,512,1024十次擴容(假設每次擴容翻倍)
而slice的底層其實還是陣列,所以每次擴容都需要建立一個兩倍長度的新陣列,迴圈原陣列的值複製到新陣列中,所以當slice值很大的時候,每次擴容其實都要損耗相當大的效能。
而如果你剛開始就把容量定成1000,那麼速度就等於給陣列賦值的速度了。
絕大部分情況下你是不需要關注 capacity 的,因為 slice 在進行 append 操作時,如果底層陣列空間容量不足,則會重新分配空間,從這一點上來看,是不需要關注 capacity 的。
那麼什麼時候需要關注 capacity?首先要明確的是上文提到的底層陣列擴容的操作是會帶來效能消耗的,因為存在陣列元素的複製和記憶體地址再分配。如果:
(1)對效能要求高
(2)在使用切片之前已經可以明確知道所需陣列空間大小
那麼就可以預先定義好 capacity,帶來一定的效能提升。
更多細節可以看下這篇文章:
https://
blog。golang。org/slices-
intro#TOC_5
考慮到效能需要關注,不考慮的話就沒問題,就當做不存在就好