數組(Array)和切片(Slice)

一個切片是一個數組片斷的描述。它包含了指向數組的指針、片斷的長度和容量(片斷的最大長度)數組

Array和Slice的區別app

  • Array是值類型,固定長度,大小是類型的一部分,當一個數組變量被賦值或者被傳遞的時候,實際上會複製整個數組。而Slice在新元素加入的時候能夠增長長度(增加到容量的上限)函數

  • 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

參考資料:

Slices使用和內幕

相關文章
相關標籤/搜索