Slice切片

董雷發表於2021-10-25

Slice切片

陣列的缺點

  • 1. Go中的陣列是值型別,換句話說,如果你將一個陣列賦值給另外一個陣列,那麼,實際上就是將整個陣列拷貝一份
  • 2. 如果Go中的陣列作為函式的引數,那麼實際傳遞的引數是一份陣列的拷貝,而不是陣列的指標。這個和C要區分開。因此,在Go中如果將陣列作為函式的引數傳遞的話,那效率就肯定沒有傳遞指標高了。

為什麼需要切片

陣列的長度不可改變,在特定場景中這樣的集合就不太適用,Go中提供了一種靈活,功能強悍的內建型別Slices切片(“動態陣列”),與陣列相比切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。切片中有兩個概念:一是len長度,二是cap容量,長度是指已經被賦過值的最大下標+1,可通過內建函式len()獲得。容量是指切片目前可容納的最多元素個數,可通過內建函式cap()獲得。切片是引用型別,因此在當傳遞切片時將引用同一指標,修改值將會影響其他的物件。

切片簡介

  • 切片是可動態變化的序列,是對陣列的引用,引用型別,遵循引用傳遞的機制
  • slice型別寫作[]T,T是slice元素型別,var s1 []int,s1就是切片變數,空中括號是切片的典型標誌

簡單案例

//建立一個陣列
var array1 [5]int = [...]int{11, 22, 33, 44, 55}
/*
建立切片,通過對陣列的索引切片
s1 是切片名
array1[1:3]代表slice引用陣列區間,索引1到索引3的值,注意取頭不取尾,
*/
s1 := array1[1:4]
fmt.Printf("array1 = %v s1 = %v len(s1) = %v cap(s1) = %v \n",array1,s1,len(s1),cap(s1))

//結果
array1 = [11 22 33 44 55] s1 = [22 33 44] len(s1) = 3 cap(s1) = 4 

切片原理

  • slice是一個輕量級資料結構,提供訪問陣列子序列元素的功能。
  • slice由三個部分構成,指標、長度、容量
  • 指標:指標指向slice第一個元素對應的陣列元素的地址。
  • 長度:slice元素的數量,不得超過容量。
  • 容器:slice開始的位置到底層資料的結尾。

切片操作

//建立陣列data
array := [...]int{0, 1, 2, 3, 4, 5}
//切片s [2,3]
slice := array[2:4]
//切片讀寫操作目標是底層陣列data,data的值會一起被修改
slice[0] += 100
slice[1] += 200
fmt.Printf("slice = %v array = %v",slice,array)
//執行結果
slice = [102 203] array = [0 1 102 203 4 5]

建立切片的方式

  • 1.定義切片,然後引用已經建立好的陣列,陣列可見
//建立陣列和切片的不同,陣列中,中括號不能為空,必須是 ...  或者是具體數字(元素個數)
var s1 []int = []int{1, 2, 3, 4, 5}
var array1 = [...]int{11, 22, 33, 44}
fmt.Printf("array1 = %v s1 = %v 長度 = %v 容量 = %v \n",array1,s1,len(s1),cap(s1))
//返回值
array1 = [11 22 33 44] s1 = [1 2 3 4 5] 長度 = 5 容量 = 5 
  • 2.內建make函式建立切片,底層陣列看不見,只能通過slice訪問元素
內建make函式,引數(型別,len,cap),注意cap大於len,容量可以省略,預設等於長度
//如果cap不傳預設容量就是長度
slice3 := make([]int, 10) 和 slice := make([]int, 10, 10) 一個意思

//簡單案例
slice := make([]int, 10, 30)
slice[0] = 11
//如果 slice[10] = 11 或者 slice[11] = 11 都會報錯,因為 下標範圍是 0 - 9 
//也就是下邊必須小於 10 ,30代表 append 的時候最多到下邊 29
//     slice = append(slice, 400)
fmt.Printf("slice = %v",slice)
//列印
slice = [11 0 0 0 0 0 0 0 0 0]
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章