本篇內(nèi)容介紹了“slice是如何擴容的”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

創(chuàng)新互聯(lián)是一家專業(yè)提供天祝藏族自治企業(yè)網(wǎng)站建設,專注與做網(wǎng)站、網(wǎng)站設計、html5、小程序制作等業(yè)務。10年已為天祝藏族自治眾多企業(yè)、政府機構等服務。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站制作公司優(yōu)惠進行中。
我擦,這么直接的嘛?
我猜是數(shù)組加鏈表,結果猜錯了0分。
翻看源碼。
runtime/slice.go
type slice struct {
array unsafe.Pointer //數(shù)據(jù)結構是簡單粗暴的數(shù)組指針
len int
cap int
}又猜錯了~
還是繼續(xù)看源碼吧
從源碼找了半天,發(fā)現(xiàn)一個這。
growslice handles slice growth during append.
so,就是你了。
func growslice(et *_type, old slice, cap int) slice { // 第三個cap,新的最小容量
//巴拉巴拉巴拉 一堆判斷
newcap := old.cap //變量存儲空間大小
doublecap := newcap + newcap //雙倍空間大小
if cap > doublecap { //如果歷史空間大于雙倍的容量,新的最小容量
newcap = cap
} else {
//如果長度小于 1024 新長度就是2倍老容量
if old.len < 1024 {
newcap = doublecap
} else {
//當大于1024 走公式 newcap += newcap / 4,直到newcap大于等于老cap
for 0 < newcap && newcap < cap {
newcap += newcap / 4
}
if newcap <= 0 {
newcap = cap
}
}
}
var overflow bool
var lenmem, newlenmem, capmem uintptr
//對et的size做匹配,獲取需要申請的空間大小
//1 不處理直接分配
//系統(tǒng)指針大小 進行計算和位運算
//2 唯一運算
//默認 相乘
switch {
case et.size == 1:
lenmem = uintptr(old.len)
newlenmem = uintptr(cap)
capmem = roundupsize(uintptr(newcap))
overflow = uintptr(newcap) > maxAlloc
newcap = int(capmem)
case et.size == sys.PtrSize:
lenmem = uintptr(old.len) * sys.PtrSize
newlenmem = uintptr(cap) * sys.PtrSize
capmem = roundupsize(uintptr(newcap) * sys.PtrSize)
overflow = uintptr(newcap) > maxAlloc/sys.PtrSize
newcap = int(capmem / sys.PtrSize)
case isPowerOfTwo(et.size):
var shift uintptr
if sys.PtrSize == 8 {
// Mask shift for better code generation.
shift = uintptr(sys.Ctz64(uint64(et.size))) & 63
} else {
shift = uintptr(sys.Ctz32(uint32(et.size))) & 31
}
lenmem = uintptr(old.len) << shift
newlenmem = uintptr(cap) << shift
capmem = roundupsize(uintptr(newcap) << shift)
overflow = uintptr(newcap) > (maxAlloc >> shift)
newcap = int(capmem >> shift)
default:
lenmem = uintptr(old.len) * et.size
newlenmem = uintptr(cap) * et.size
capmem, overflow = math.MulUintptr(et.size, uintptr(newcap))
capmem = roundupsize(capmem)
newcap = int(capmem / et.size)
}
//如果append一次超過過多的元素新增,直接報錯,越界,超出容量大小
if overflow || capmem > maxAlloc {
panic(errorString("growslice: cap out of range"))
}
var p unsafe.Pointer //申請新的內(nèi)存,并把指針指向p
if et.ptrdata == 0 {
p = mallocgc(capmem, nil, false)
memclrNoHeapPointers(add(p, newlenmem), capmem-newlenmem)
} else {
p = mallocgc(capmem, et, true)
if lenmem > 0 && writeBarrier.enabled {
bulkBarrierPreWriteSrcOnly(uintptr(p), uintptr(old.array), lenmem)
}
}
//將老的數(shù)據(jù)移動到新的數(shù)據(jù)
memmove(p, old.array, lenmem)
return slice{p, old.len, newcap}
}其實可以看出,golang的切片擴容是比較粗暴的,直接賦值拷貝。不過,golang區(qū)分的長度和容量兩種單位計量,一般會提前分配足夠的cap,可以減少maclloc的次數(shù)。
“slice是如何擴容的”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質量的實用文章!
文章題目:slice是如何擴容的
文章來源:http://chinadenli.net/article26/gghjjg.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供手機網(wǎng)站建設、網(wǎng)站營銷、網(wǎng)站導航、網(wǎng)站制作、移動網(wǎng)站建設、外貿(mào)網(wǎng)站建設
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)