Go 切片(slice)

Go中,數(shù)組的長度是不可變的,但是Go提供了一種靈活的內(nèi)置類型:切片(也稱為動態(tài)數(shù)組)。

切片的長度不固定,可以追加元素,也可以擴容。

slice 的本質(zhì)

slice是引用類型,是一個指向數(shù)組的指針。

在內(nèi)存中,一個slice是一個結(jié)構(gòu)體:

struct Slice
{
    byte* array;    // actual data
    uintgo  len;    // number of elements
    uintgo  cap;    /// allocated number of elements
}

所以,一個slice是一個包含三個域的結(jié)構(gòu)體:指向slice中第一個元素的指針,slice的長度,slice的容量。

slice的長度是slice中元素的個數(shù),slice的容量是slice中最多能有的元素的個數(shù)。

因此長度是下標(biāo)操作的上界,如x[i]中 i 必須小于長度。容量是分割操作的上界,如x[i:j]中 j 不能大于容量。

如下圖:

定義切片

var s1 []int    // 聲明一個未指定大小的數(shù)組來定義切片
var s2 []int = make([]int, len)  // 使用make() 來創(chuàng)建切片
s3 := make([]int, len)   // 同上
s4 := make([]int, len, cap)  // 也可以指定容量。

切片未初始化之前默認(rèn)為 nil,長度為 0 。

內(nèi)置函數(shù) len() 和 cap() 提過了獲取切片長度和容量的方法。

切片初始化和截取

s1 := []int{1, 2, 3} // 直接初始化,其 cap = len = 3

arr := [...]int{1, 3, 5, 7, 9, 11}  // arr 是一個數(shù)組
s2 := arr[:]   // 切片s2 是數(shù)組arr的引用
s3 := arr[2:5]  // s3 = [5, 7, 9]
s3 := arr[2:]   // s3 = [5 7 9 11]  缺省endIndex時,就直到arr的最后一個元素
s3 := arr[:3]   // s2 = [1, 2, 5]   缺省startIndex時,就從arr的第一個元素開始

s4 := s3[startIndex:endIndex]  // 用切片s3 初始化 s4,但它們只是不同的結(jié)構(gòu)體,指向了同一片內(nèi)存區(qū),共享底層數(shù)據(jù)

切片追加元素

內(nèi)置函數(shù) append() 可以向切片追加新元素。

s1 = append(s1, 4)     // s1 = [1 2 3 4]
s1 = append(s1, 5, 6)  // s1 = [1 2 3 4 5 6]

對 slice 進(jìn)行 append 操作時,可能會造成 slice 自動擴容。其擴容時的規(guī)則是:

  • 如果新的大小是當(dāng)前大小的2倍以上,則大小增長為新大小
  • 否則循環(huán)一下操作:如果當(dāng)前大小小于1024,按每次2倍增長,否則每次按當(dāng)前大小的 1/4 增長。直達(dá)增長的大小超過或等于新大小。

我們通常不知道 append 調(diào)用是否導(dǎo)致了內(nèi)存的重新分配,因此我們不能確認(rèn)新的slice和原始的slice是否引用的是相同的底層數(shù)組空間。同樣,我們不能確認(rèn)在原先的slice上的操作會不會影響到新的 slice,因此,通常是將 append 返回的結(jié)果直接復(fù)制給輸入的 slice 變量, 即 s = append(s, r) 。

手動擴容

s5 := make([]int, len(s3), (cap(s3))*2)  // 創(chuàng)建切片s5 是 s3 的兩倍容量
copy(s5, s3) // 拷貝 s3 的內(nèi)容到 s5

slice作為函數(shù)參數(shù)

向函數(shù)傳遞 slice 將允許在函數(shù)內(nèi)部修改底層數(shù)組的元素。

其他

  • 不能使用 == 來判斷兩個slice 是給含有全部相同元素
  • slice 唯一合法的比較是 和 nil 比較。
  • 判斷 slice 是否為空,使用 len(s) == 0 , 而不是 s == nil 。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容