Go基礎數據結構學習——slice
slice
-
Slice切片:是一個數組某部分的引用,在內存中是一個包含三個域的結構體,第一個是指向數據的第一個元素的指針,第二個是切片的長度,第三個是切片的容量
type slice struct { array unsafe.Pointer len int cap int }
-
slice不能簡單使用==來測試兩個slice是否擁有相同的元素,對於引用類型,操作符==檢查的是引用相等性,即是否指向相同的元素。如果切片類型是字節([]byte),可以使用bytes.Equal比較,其他的類型就不可以了。slice唯一允許的比較操作就是和nil做比較。
func Equal(a, b []string) bool { if len(a) != len(b){ return false } for i := range a{ if a[i] != b[i]{ return false } } return true }
-
注意:
-
slice的零值是nil
-
值爲nil的slice長度和容量都是0
var s []string // len(s) == 0,s == nil s = nil // len(s) == 0,s == nil s = []string(nil) // len(s) == 0,s == nil s = []string{} // len(s) == 0,s != nil s = make([]string, 3) // len(s) == 0,s != nil
檢查slice是否是空可以使用len(s) == 0而不是s == nil,s爲nil也可能爲空
-
重新切分切片不會複製底層數組
-
make([]T, len) 和make([]T, len, cap):初始化的時候如果使用make([]T, 3) 的含義是len=3,且 cap=3的數組,此時數組中已經存在3個nil的元素了,如果使用make([]T, 0, 3)含義是len=0,cap=3的數組,數組中爲空
-
數組是值拷貝而切片是引用
-
-
slice的擴充:每次調用都必須檢查slice是否有足夠的容量來存儲數組中的新元素,
-
如果slice容量足夠,他就會定義一個新的slice,仍然應用原始底層數組,然後將新元素複製到新的位置並返回新的slice;
-
如果新的大小是當前大小的兩倍以上,則大小爲新大小
-
如果當前大小小於1024,按每次兩倍增長,否則按當前大小四分之一增長,知道增長的大小超過或等於新大小
// runtime/slice.go func growslice(et *_type, old slice, cap int) slice { // ......省略 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 } } } // ......省略 }
-