在 Go 語言中,切片(Slice)是一種動態序列的資料結構,能夠方便地存儲和操作多個相同類型的元素。切片相比於陣列,更具有彈性,因為它的大小是可變的,可以根據需要動態增長或縮小。切片在處理集合型資料時非常實用,讓你能夠輕鬆地新增、刪除、修改和操作元素,同時避免了固定大小的限制。
切片是由一個指向陣列的指針、切片長度和切片容量組成的。切片的長度指的是切片中實際包含的元素個數,而切片的容量則是從切片開始的底層陣列中能夠訪問的元素個數。切片的容量可以大於或等於切片的長度。
在 Go 中,宣告和初始化切片可以使用以下的語法:
var slice1 []int // 創建一個整數切片,大小和容量都是 0
slice2 := []string{"A", "B", "C"} // 創建一個包含三個字串元素的切片
slice3 := make([]int, 5) // 創建一個整數切片,大小為 5,容量也為 5
slice4 := make([]int, 3, 5) // 創建一個整數切片,大小為 3,容量為 5
Go語言中有個內件函式append()
,可以用來新增元素到切片中,這使得切片能夠根據需求動態增長。
numbers := []int{10, 20, 30}
numbers = append(numbers, 40, 50) // 新增兩個元素到切片
需要注意的是,如果切片的容量不足以容納新增的元素,append()
函式會創建一個新的切片,並將舊的元素和新的元素一同複製到新的切片中。
切片的元素可以通過索引來存取,索引從 0 開始計數。
numbers := []int{10, 20, 30, 40, 50}
firstNumber := numbers[0] // 存取第一個元素,值為 10
secondNumber := numbers[1] // 存取第二個元素,值為 20
numbers[2] = 35 // 修改切片中的元素,將第三個元素改為 35
可以使用切片的切割操作來獲取部分切片,這可以通過指定切片的起始索引和結束索引來實現:
numbers := []int{10, 20, 30, 40, 50}
subSlice := numbers[1:4] // 從第二個元素到第四個元素的子切片,值為 [20 30 40]
[:]
:使用 [:]
語法可以獲得完整的切片,即包含所有元素的切片。[x:]
:這種語法表示從索引 x
開始,提取所有直到切片結尾的元素。[:x]
:這種語法表示提取從開頭到索引 x-1
的元素,不包含索引 x
的元素。切片的遍歷可以使用傳統的索引方式,或者使用 range
來簡化遍歷過程。
numbers := []int{10, 20, 30, 40, 50}
// 使用傳統的索引方式遍歷切片
for i := 0; i < len(numbers); i++ {
fmt.Println(numbers[i])
}
// 使用 range 遍歷切片
for index, value := range numbers {
fmt.Printf("索引:%d,值:%d\n", index, value)
}
for i := range numbers {
fmt.Println(numbers[i])
}
雖然切片沒有內建的刪除方法,不過可以使用切片的切割操作,將不需要的元素排除在外。
slice := []int{10, 20, 30, 40, 50}
indexToDelete := 2
slice = append(slice[:indexToDelete], slice[indexToDelete+1:]...) // 刪除索引 2 的元素
切片的容量就是指,你從切片開始的位置能夠往後訪問到的元素數量。當你在切片上進行新增元素的操作時,如果新加進來的元素數量超過了切片目前的容量,Go 語言會做一些事情:它會重新搞一個更大的陣列,然後把舊的元素都複製到這個新陣列中。這個過程會花一些時間,也就是所謂的性能開銷。
package main
import "fmt"
func main() {
numbers := []int{1, 2, 3}
fmt.Println("長度:", len(numbers)) // 輸出:長度:3
fmt.Println("容量:", cap(numbers)) // 輸出:容量:3
slice := numbers[1:2]
fmt.Println("切片:", slice) // 輸出:切片:[2]
fmt.Println("切片長度:", len(slice)) // 輸出:切片長度:1
fmt.Println("切片容量:", cap(slice)) // 輸出:切片容量:2
// 切片的容量是從切片的起始索引開始計算,一直到底層陣列的末尾索引。因此容量為2
// 新增元素超過切片容量時,會自動擴容並分配更大的底層陣列
slice = append(numbers, 4) // 新切片為 [1, 2, 3, 4]
fmt.Println("切片:", slice) // 輸出:切片:[1 2 3 4]
fmt.Println("切片長度:", len(slice)) // 輸出:切片長度:4
fmt.Println("切片容量:", cap(slice)) // 輸出:切片容量:6
}
slice1 := []int{1, 2, 3}
slice2 := slice1
slice2[0] = 3
fmt.Println(slice1, slice2) // 輸出:[3 2 3] [3 2 3]
在這裡,修改 slice2
的值同樣影響了 slice1
,因為它們引用同一份底層數據。這是切片和陣列之間的一個重要區別。
range
遍歷切片,可以輕鬆地過濾或轉換切片中的元素,進行處理和計算。sort
套件進行排序,並使用二分搜尋等技術進行搜尋。// 將切片中的所有元素乘以 2
numbers := []int{1, 2, 3, 4, 5}
for i := range numbers {
numbers[i] *= 2
}
// 過濾出大於 3 的元素
filteredNumbers := []int{}
for _, num := range numbers {
if num > 3 {
filteredNumbers = append(filteredNumbers, num)
}
}
func modifySlice(slice []int) {
slice[0] = 100
}
numbers := []int{1, 2, 3}
modifySlice(numbers)
切片是 Go 語言中非常實用的資料結構,它解決了陣列大小固定的限制,讓你能夠輕鬆地處理動態大小的集合型資料。切片的操作包括取得、修改、新增、刪除等,讓你可以靈活地處理資料集合。
在遍歷切片時,range
很方便地提供了索引和值,讓你能夠輕鬆地訪問切片中的元素。切片的特性和優勢使得它在處理動態數據集合時成為 Go 程式設計中的一個重要工具。