【go原始碼分析】go原始碼之slice原始碼分析
阿新 • • 發佈:2018-11-09
Go 語言切片是對陣列的抽象。
Go 陣列的長度不可改變,與陣列相比切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。
len() 和 cap() 函式
切片是可索引的,並且可以由 len() 方法獲取長度。
切片提供了計算容量的方法 cap() 可以測量切片最長可以達到多少。
空(nil)切片
一個切片在未初始化之前預設為 nil,長度為 0
結構體
slice結構體
一個指向array地址的指標,slice的長度len和容量cap
type slice struct {
array unsafe.Pointer
len int
cap int
}
1. makeslice函式
呼叫mallocgc分配連續的地址
func makeslice(et *_type, len, cap int) slice { // NOTE: The len > maxElements check here is not strictly necessary, // but it produces a 'len out of range' error instead of a 'cap out of range' error // when someone does make([]T, bignumber). 'cap out of range' is true too, // but since the cap is only being supplied implicitly, saying len is clearer. // See issue 4085. maxElements := maxSliceCap(et.size) if len < 0 || uintptr(len) > maxElements { panicmakeslicelen() } if cap < len || uintptr(cap) > maxElements { panicmakeslicecap() } p := mallocgc(et.size*uintptr(cap), et, true) return slice{p, len, cap} }
2. growslice函式
slice擴大容量函式,這塊可以看出來怎麼增長容量
- < 1024,按照兩倍增長
- 否則按照1.25倍增長
- 擴容會涉及資料拷貝,產生效能開銷
newcap := old.cap doublecap := newcap + newcap if cap > doublecap { newcap = cap } else { if old.len < 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 } } }