Go語言核心 slice切片

2021-07-10 16:47:53 字數 1750 閱讀 6780

slice是長度可變的元素序列(陣列不可變),每個元素都有相同的型別。slice型別寫作t,其中t代表slice中的元素型別;slice和陣列寫法很像,只是沒有指定長度。

陣列和slice之間的聯絡非常緊密。slice是非常輕量的資料結構,它是引用型別,指向底層的乙個陣列,該陣列被稱之為slice的底層陣列,slice可以訪問底層陣列的某個子串行,也可以訪問整個陣列。乙個slice由三個部分組成:指標、長度、容量,指標指向了slice中第乙個元素對應的底層陣列元素的位址,因為slice未必是從陣列第乙個元素開始,因此slice中的第乙個元素未必是陣列中的第乙個元素。長度對應slice中的元素數目,長度是不能超過容量的;容量一般是從slice中第乙個元素對應底層陣列中的開始位置,到底層陣列的結尾的長度。內建函式len和cap分別返回乙個slice的長度和容量。

多個slice可以共享底層的陣列,甚至它們引用的底層陣列部分可以重疊。圖4.1表示了乙個陣列,它的元素是每個月份的字串名,還有兩個slice,它們重疊引用了底層陣列。陣列定義:

months := [...]string

這裡一月份是months[1],十二月是months[12]。通常來說,陣列第一元素索引從0開始,但是月份一般是從1月開始到12月,因此在宣告陣列時,我們跳過了第0個元素,這裡,第0個元素會被預設初始化為""(空字串)。

下面介紹切片操作s[i:j],這裡0 ≤ i≤ j≤ cap(s),該操作會建立乙個新的slice,引用s中從第i個元素到第j-1個元素的字序列,新的slice有j-i個元素。如果省略下標i:s[:j],實際上代表s[0:j];如果省略下標j:s[i:],代表s[0:len(s)]。因此months[1:13]操作將引用全部月份,和months[1:]操作等價。months[:]則是引用整個陣列。下面分別表示第二個季度和北方的夏天:

q2 := months[4:7]

summer := months[6:9]

fmt.println(q2) // ["april" "may" "june"]

fmt.println(summer) // ["june" "july" "august"]

兩個slice有重疊部分:六月份,下面是乙個包含相同月份的測試(效能不高):

for _, s := range summer {

for _, q := range q2 {

if s == q {

如果slice操作的下標超過cap(s)將導致panic,如果超過len(s)則意味著擴充套件slice(不能超過cap(s)),因為新slice的長度會變大:

fmt.println(summer[:20]) // panic: out of range

endlesssummer := summer[:5] // 在容量允許內擴充套件summer

fmt.println(endlesssummer) // "[june july august september october]"

另外,字串的slice操作和byte的slice操作是很相似的。它們都表現為x[m:n],並且都返回原始序列的子串行,底層陣列也都是原始的序列,因此slice操作是常量級別的時間複雜度。若x[m:n]的目標是字串,則生成乙個子串;若目標是byte,則生成新的byte。

因為slice引用包含了指向底層陣列的指標,因此向函式傳遞slice後,函式可以在內部對slice的底層陣列進行更改。換而言之,複製slice就是為底層陣列建立乙個新的引用,代價是非常低的(其實就是複製乙個含有三個欄位的struct)。下面的reverse函式對int型別的slice進行就地反轉(無記憶體分配),它可以用於任意長度的slice:

Go語言切片 Slice

python裡面切片是一種操作,用於取list裡面元素。而go語言的切片則是一種資料型別,而不是一種操作。go語言中提供了切片 slice 作為一種更為靈活 功能強悍的內建型別,它其實是陣列的一種抽象。切片的原始碼 type slice struct slice是原陣列在記憶體中的位址的乙個指標,它...

go語言基礎 切片 slice

理解為變長的陣列 a 切片建立 s1 int s2 make t,len,cap arr 5 int s3 arr start end 切割陣列 start,end s4 arr b 切片的型別 資料型別 切片屬於引用型別 s1 int s2 s1 packagemain import fmt fu...

Go語言14 切片 Slice

go 語言切片是對陣列的抽象。go 陣列的長度不可改變,在特定場景中這樣的集合就不太適用,go中提供了一種靈活,功能強悍的內建型別切片 動態陣列 與陣列相比切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。你可以宣告乙個未指定大小的陣列來定義切片 var identifier typ...