Go語言中的切片(slice)基礎
引子
在Go語言中,陣列的長度是固定的,且陣列長度屬於型別的一部分。這種特性限制了陣列的靈活性,無法動態擴容,對複雜情況難以適用。
切片的定義
切片(Slice)是一個擁有相同型別元素的可變長度的序列。它基於陣列型別進行了封裝,具有很大的靈活性,支援自動擴容。切片是引用型別,內部結構包含地址、長度和容量。通常用於快速操作一塊資料集合。
宣告切片的語法如下:
var name []T
其中name
表示變數名,T
表示切片中的元素型別。示例如下:
func main() {
var a []string //宣告一個字串切片
var b = []int{} //宣告一個整型切片並初始化
var c = []bool{false, true} //宣告一個布林切片並初始化
fmt.Println(a) //[]
fmt.Println(b) //[]
fmt.Println(c) //[false true]
fmt.Println(a == nil) //true
fmt.Println(b == nil) //false
fmt.Println(c == nil) //false
}
切片的長度和容量
切片擁有自己的長度和容量。可以使用內建的len()
函式求長度,使用內建的cap()
函式求容量。
切片表示式
切片表示式用於從字串、陣列、指向陣列的指標或切片中構造子字串或切片。切片表示式有兩種形式:簡單形式和完整形式。
簡單切片表示式
切片基於陣列,可以透過切片表示式得到。切片表示式中的low
和high
表示一個索引範圍(左包含,右不包含),例如:
func main() {
a := [5]int{1, 2, 3, 4, 5}
s := a[1:3]
fmt.Printf("s:%v len(s):%v cap(s):%v\n", s, len(s), cap(s))
}
輸出結果:
s:[2 3] len(s):2 cap(s):4
可以省略切片表示式中的任何索引:
a[2:] // 等同於 a[2:len(a)]
a[:3] // 等同於 a[0:3]
a[:] // 等同於 a[0:len(a)]
完整切片表示式
對於陣列、指向陣列的指標或切片,支援完整切片表示式:
a[low : high : max]
例如:
func main() {
a := [5]int{1, 2, 3, 4, 5}
t := a[1:3:5]
fmt.Printf("t:%v len(t):%v cap(t):%v\n", t, len(t), cap(t))
}
輸出結果:
t:[2 3] len(t):2 cap(t):4
使用make()
函式構造切片
make()
函式用於動態建立一個切片:
a := make([]int, 2, 10)
fmt.Println(a) //[0 0]
fmt.Println(len(a)) //2
fmt.Println(cap(a)) //10
切片的本質
切片的本質是對底層陣列的封裝,包含底層陣列的指標、切片的長度(len
)和切片的容量(cap
)。
判斷切片是否為空
檢查切片是否為空,應該使用len(s) == 0
而不是s == nil
。
切片不能直接比較
切片之間不能直接使用==
運算子比較,只能與nil
比較。
切片的賦值與複製
切片賦值操作是引用傳遞,兩個切片共享同一個底層陣列。使用copy()
函式可以將一個切片的資料複製到另一個切片:
func main() {
a := []int{1, 2, 3, 4, 5}
c := make([]int, 5)
copy(c, a)
fmt.Println(a) //[1 2 3 4 5]
fmt.Println(c) //[1 2 3 4 5]
}
切片遍歷
切片的遍歷方式與陣列相同,支援索引遍歷和for range
遍歷。
使用append()
函式為切片新增元素
append()
函式可以為切片動態新增元素:
func main() {
var s []int
s = append(s, 1) // [1]
s = append(s, 2, 3, 4) // [1 2 3 4]
s2 := []int{5, 6, 7}
s = append(s, s2...) // [1 2 3 4 5 6 7]
}
切片的擴容策略
切片的容量不足時,會按照一定的策略進行擴容。具體策略可以參考Go原始碼中的實現。
從切片中刪除元素
Go語言中沒有專用方法刪除切片元素,可以使用切片的特性:
a = append(a[:index], a[index+1:]...)
結論
切片是Go語言中一個非常靈活和強大的資料結構,理解切片的底層實現和操作方式對於編寫高效的Go程式碼非常重要。透過本文對切片的基本介紹和使用示例,相信讀者已經對Go語言中的切片有了一個較為全面的認識。