Go | 初步了解「列表」型別
💬 簡介
在程式設計中,「列表」型別是一個非常常用的資料結構,它可以幫助我們儲存和管理一組有序的資料。在 Go 語言中,我們常用兩種資料結構來實現列表:切片(slice)和雙向鏈結串列(container/list)。這兩者各有優缺點,適用於不同的情境。
本文將介紹 Go 中的列表型別,並深入探討切片和雙向鏈結串列的差異及使用場景。
圖片來源:Gophers(地鼠造型的原創者為 Renee French)
✨ 切片:Go 語言中的靈活列表
切片(slice) 是 Go 語言中一種非常靈活的資料結構。與陣列不同,切片可以動態增長和縮小。它不僅是對陣列的一層封裝,更具彈性,特別適用於動態大小的資料處理。
1️⃣ 宣告與初始化切片
我們可以用 []
宣告切片,並使用 append
函式動態地添加元素。
- 範例:創建與初始化切片
1
2
3
4
5
6
7
8
9package main
import "fmt"
func main() {
var numbers []int
numbers = append(numbers, 1, 2, 3)
fmt.Println(numbers) // 輸出: [1 2 3]
}📝 在這個範例中,我們創建了一個空的切片並使用
append
向切片中添加元素。
2️⃣ 訪問切片的元素
與陣列類似,可以使用索引來訪問切片的元素。
- 範例:訪問切片元素
1
2
3
4
5
6
7
8package main
import "fmt"
func main() {
numbers := []int{1, 2, 3, 4}
fmt.Println(numbers[2]) // 輸出: 3
}📝 這個範例中,我們通過索引訪問了切片中的第三個元素。
3️⃣ 切片的增長與調整
切片可以隨著需要自動增長,並且提供了多種靈活的操作方法。
- 範例:調整切片大小
1
2
3
4
5
6
7
8
9package main
import "fmt"
func main() {
numbers := []int{1, 2, 3, 4, 5}
numbers = append(numbers, 6) // 添加元素
fmt.Println(numbers) // 輸出: [1 2 3 4 5 6]
}📝 在這個範例中,我們使用
append
函式將元素添加到切片的末尾,切片會自動擴展。
🔄 列表的其他實現:container/list
除了使用切片來實現列表,Go 還提供了一個名為 container/list
的標準庫包,實現了雙向鏈結串列。雙向鏈結串列的最大優勢在於其插入與刪除元素的操作非常高效,特別是當元素需要經常被插入或刪除時。
1️⃣ 使用 container/list
創建雙向鏈結串列
首先,必須引入 container/list
包,並使用它來創建一個雙向鏈結串列。
- 範例:初始化一個空的鏈結串列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package main
import (
"container/list"
"fmt"
)
func main() {
// 創建一個空的雙向鏈結串列
l := list.New()
// 向鏈結串列中添加元素
l.PushBack(1) // 在末尾插入
l.PushFront(2) // 在開頭插入
// 遍歷並輸出鏈結串列中的元素
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
}📝 在這個範例中,我們使用
PushBack
向串列尾部插入元素,並使用PushFron
t 向串列頭部插入元素。最後通過l.Front()
遍歷鏈結串列中的元素。
2️⃣ 插入與刪除操作
與切片相比,container/list
使得插入與刪除元素變得更加高效,特別是在中間插入或刪除元素時。
- 範例:在中間插入元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package main
import (
"container/list"
"fmt"
)
func main() {
// 初始化鏈結串列
l := list.New()
// 添加元素
e1 := l.PushBack(1)
e2 := l.PushBack(2)
// 在中間插入元素
l.InsertBefore(3, e2) // 在 e2 前插入 3
l.InsertAfter(4, e1) // 在 e1 後插入 4
// 輸出結果
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
}📝 在這個範例中,我們使用
InsertBefore
和InsertAfter
在特定位置插入元素,這些操作比在切片中間進行插入操作更加高效。
🚀 切片與 container/list 的比較
切片(Slice)
- 優勢:
- 查詢速度非常快,適合隨機存取元素。
- 記憶體空間連續,處理大量資料時更為高效。
- 靈活,可以動態增減元素。
- 限制:
- 插入或刪除中間元素的效率較低,因為必須調整切片中元素的位置。
雙向鏈結串列(container/list
)
- 優勢:
- 插入和刪除元素的操作非常高效,特別是對中間元素的操作。
- 更適合頻繁增刪元素的場景。
- 限制:
- 查詢速度較慢,必須遍歷串列中的每個元素。
- 記憶體佔用較高,因為每個元素需要存儲指向前後元素的指標。
何時選擇使用
- 如果你的應用需要頻繁操作(插入、刪除)中間元素,則
container/list
是更好的選擇。 - 如果你的應用需要高效的隨機訪問並且較少進行插入或刪除操作,那麼切片將是更理想的選擇。
🎯總結
切片和雙向鏈結串列(container/list
)是 Go 中常用的兩種列表實現方式,各自有其優勢和限制。理解它們的特性和使用場景,能幫助你更好地選擇最適合你的應用需求的資料結構。
在實際開發中,選擇哪種資料結構取決於操作的需求:如果你需要頻繁進行插入或刪除操作,container/list
是個不錯的選擇;如果你主要需要處理動態資料並且訪問速度至關重要,則切片更為合適。
最後建議回顧一下 Go | 菜鳥教學 目錄,了解其章節內容。
註:以上參考了
Go
Go-container/list