一個切片是一個數組片斷的描述。它包含了指向數組的指針、片斷的長度和容量(片斷的最大長度)數組
Array和Slice的區別:app
Array是值類型,固定長度,大小是類型的一部分,當一個數組變量被賦值或者被傳遞的時候,實際上會複製整個數組。而Slice在新元素加入的時候能夠增長長度(增加到容量的上限)函數
slice 一個切片是一個數組片斷的描述。它包含了指向數組的指針,片斷的長度和容量(底層數組的長度)。 3d
定義數組:指針
<!-- lang: cpp --> var a [32]byte var b [5] struct { x, y int32 } //記錄類型的數組 var c [1000]*float64 //數組元素是指向浮點型的指針 var d [3][5]int //二維數組 var e [2][2][2]float64 // 三維數組,跟這個同樣 [2]([2]([2]float64)) //也能夠直接賦值,無需指定數據長度, //變量聲明中的...至關於指定了數組的長度 var p [6]int = [...]int{2, 3, 5, 7, 11, 13} var p = [...]int{2, 3, 5, 7, 11, 13} p := [...]int{2, 3, 5, 7, 11, 13} //上面定義的p至關於類型[6]int
定義Slice:code
<!-- lang: cpp --> //與數組的聲明相似,只不過少了三點... var p = []int{2, 3, 5, 7, 11, 13} p := []int{2, 3, 5, 7, 11, 13} //使用s[lo:hi]進行切片,這種操做會返回一個新的指向數組的指針,而不會複製數組 //s[lo:hi]表示從 lo 到 hi-1 的 slice 元素 x := p[1:4] //引用數組的一部分 x := p[:3] //從0開始,截取到p[2] x := p[4:] //截取到數組結尾,即len(p) //使用make函數建立slice a := make([]int, 5) // len(a)=5 b := make([]int, 0, 5) // len(b)=0, cap(b)=5
slice 能夠經過「從新切片」來擴容(增加到容量上限):blog
<!-- lang: cpp --> b = b[:cap(b)] // len(b)=5, cap(b)=5 b = b[1:] // len(b)=4, cap(b)=4
若是要動態增長slice的容量,則須要新建一個slice並把舊slice的數據複製過去圖片
<!-- lang: cpp --> //把s擴容兩倍 t := make([]byte, len(s), (cap(s)+1)*2)//加1是爲了防止cap(s)==0這種狀況 copy(t, s) //使用內建函數copy複製slice s = t
內建函數append,能夠在slice後面添加一個元素或另外一個slice,當超出slice的容量上限時會再建立一個更大的數組,並把原slice的值複製到新數組內存
<!-- lang: cpp --> a := make([]int, 1)// a == []int{0} a = append(a, 1, 2, 3)//自動擴容 a == []int{0, 1, 2, 3} //添加另外一個slice a := []string{"John", "Paul"} b := []string{"George", "Ringo", "Pete"} a = append(a, b...) // 至關於 "append(a, b[0], b[1], b[2])"
slice 的零值是 nil,一個 nil 的 slice 的長度和容量是 0get
<!-- lang: cpp --> var z []int //定義一個空的指針,z==nil,len(z)=0, cap(z)=0 z = make([]byte, 5, 5)//分配內存 z == []byte{0, 0, 0, 0, 0}
關於內存回收
當數組沒被引用時,該數組的內存會被回收,所以使用slice時必須注意是否須要保留整個數組。例如,數組有一萬個元素,但slice只引用了其中10個,而且後續的處理也只須要這10個,這就會致使額外的9990元素都保留在內存裏。解決方法是把這10個元素複製到一個新的slice裏,並把舊slice置爲nil
參考資料: