📢 本文由 gemini-3-flash-preview 翻譯
Golang 系列
Hello GoLang:
https://blog.yexca.net/archives/154
GoLang (var and const) 變數與常數:
https://blog.yexca.net/archives/155
GoLang (func) 函式:
https://blog.yexca.net/archives/156
GoLang (slice and map) 切片: 本文
GoLang (OOP) 物件導向:
https://blog.yexca.net/archives/162
GoLang (reflect) 反射:
https://blog.yexca.net/archives/204
GoLang (struct tag) 結構體標籤:
https://blog.yexca.net/archives/205
GoLang (goroutine) Go 協程:
https://blog.yexca.net/archives/206
GoLang (channel) 通道:
https://blog.yexca.net/archives/207
Go 的切片 (Slice) 是對陣列 (Array) 的抽象
陣列
陣列的長度不可改變
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| package main
import "fmt"
func main() {
// 定義方式一
var arr1 [10]int
// 遍歷
for i := 0; i < len(arr1); i++ {
fmt.Println("arr1[", i, "]:", arr1[i])
}
// 定義方式二,賦值
arr2 := [10]int{0, 1, 2, 3}
// range 遍歷
for index, value := range arr2 {
fmt.Println("index =", index, "value =", value)
}
// 定義不同長度
var arr3 [4]int
fmt.Printf("type of arr1 is %T\n", arr1) // [10]int
fmt.Printf("type of arr1 is %T\n", arr2) // [10]int
fmt.Printf("type of arr1 is %T", arr3) // [4]int
}
|
編譯執行後可以發現 arr3 與 arr1, arr2 型別不同,那麼在定義函式形式參數時也需要指定相應型別
1
2
3
4
5
| func test(arr [4]int) {
for i := 0; i < len(arr); i++ {
fmt.Println("fmt_arr[", i, "]:", arr[i])
}
}
|
上述函式只能傳遞 arr3,且為值傳遞 (Pass by Value),修改值不會影響原始資料
定義切片
與陣列相比,切片長度不固定,可以追加元素 (動態陣列),在追加時可能會使切片的容量增大
定義切片可以透過宣告一個未指定大小的陣列
1
2
3
| var name []type
// 例如
var s []int
|
或者使用 make() 函式來建立切片
1
2
3
| var slice []type = make([]type, len) // len 為切片初始長度
// 也可以簡寫為
slice := make([]type, len)
|
可以使用選用參數 capacity 指定容量,省略時與 length 相同
1
| var slice []type = make([]type, length, capacity)
|

切片初始化
直接初始化
將陣列區間初始化為切片,從 startIndex 到 endIndex-1,這兩個值都可以省略
1
| s := arr[startIndex:endIndex]
|
省略 startIndex 或 endIndex 表示從第一個元素開始索引或索引到最後一個元素
len() 和 cap()
切片是可以透過索引存取的,透過 len() 函式獲取長度
而 cap() 為計算容量的方法,可以測量切片最長可以達到多少
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| package main
import "fmt"
// 切片傳遞為參考傳遞 (引用傳遞),函式內修改會影響原始資料
func printSlice(slice []int) {
fmt.Printf("len=%d, cap=%d, slice=%v", len(slice), cap(slice), slice)
}
func main() {
s := make([]int, 3, 5)
printSlice(s)
}
/*
* 輸出
* len=3, cap=5, slice=[0 0 0]
*/
|
空切片
一個切片在未初始化之前預設為 nil (空切片),長度為 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| package main
import "fmt"
func printSlice(slice []int) {
fmt.Printf("len=%d, cap=%d, slice=%v\n", len(slice), cap(slice), slice)
}
func main() {
var s []int
printSlice(s)
// 判斷是否為空
if s == nil {
fmt.Println("slice is empty")
}
}
|
切片截取
透過設定上下限截取切片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| package main
import "fmt"
func printSlice(slice []int) {
fmt.Printf("len=%d, cap=%d, slice=%v\n", len(slice), cap(slice), slice)
}
func main() {
s := []int{0, 1, 2, 3, 4, 5, 6, 7}
// 打印原始切片
fmt.Println(s)
// 從 2 (包含) 到 5 (不包含)
printSlice(s[2:5])
// 從第一個到 5 (不包含)
printSlice(s[:5])
// 從第二個到最後一個
printSlice(s[2:])
// 這樣賦值修改 subS 將會影響到 s
subS := s[1:6]
printSlice(subS)
}
|
append() 和 copy()
增加切片的容量與複製切片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| package main
import "fmt"
func printSlice(slice []int) {
fmt.Printf("len=%d, cap=%d, slice=%v\n", len(slice), cap(slice), slice)
}
func main() {
var s []int
printSlice(s)
// 增加一個元素
s = append(s, 0)
printSlice(s)
// 增加多個元素
s = append(s, 1, 2, 3, 4)
printSlice(s)
// 建立一個容量為 s 兩倍的 s2
s2 := make([]int, len(s), cap(s)*2)
// 複製 s 到 s2,此時修改 s2 不影響 s
copy(s2, s)
printSlice(s2)
}
|
切片的擴充:如果追加的值超過容量,則容量通常會增加為原來的兩倍
map
map 有兩種宣告方式
1
2
3
4
5
6
7
8
9
10
11
| package main
import "fmt"
func main() {
var map1 = make(map[string]string)
// 插入資料
map1["one"] = "1"
map1["two"] = "2"
fmt.Println(map1) // map[one:1 two:2]
}
|
第二種
1
2
3
4
5
6
7
8
9
10
11
| package main
import "fmt"
func main() {
map1 := map[string]string{
"one": "1",
"two": "2",
}
fmt.Println(map1)
}
|
map 巢狀
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| package main
import "fmt"
func main() {
map1 := make(map[string]map[string]string)
map1["first"] = make(map[string]string, 2)
map1["first"]["one"] = "1"
map1["first"]["two"] = "2"
fmt.Println(map1)
}
/*
* 輸出
* map[first:map[one:1 two:2]]
*/
|
修改、遍歷與刪除
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| package main
import "fmt"
func main() {
map1 := make(map[string]map[string]string)
map1["first"] = make(map[string]string, 2)
map1["first"]["one"] = "1"
map1["first"]["two"] = "2"
// 修改
map1["first"]["one"] = "one"
fmt.Println(map1)
// 遍歷
for key, value := range map1{
fmt.Println("key =", key, "value =", value)
}
// 刪除
delete(map1, "first")
fmt.Println(map1)
}
|
判斷是否有某值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| package main
import "fmt"
func main() {
map1 := make(map[string]string)
map1["one"] = "1"
val, ok := map1["one"]
if ok {
fmt.Println(val)
} else {
fmt.Println("empty")
}
}
|