Go使用Array、Slice與Map的介紹

Posted by Kubeguts on 2021-02-16

這篇主要介紹如何在Golang底下使用Array, Slice, Map等操作技巧

array用法

新增array方式

1. 透過 []

1
2
var arr [5]int
fmt.Println("array arr:", a)

2. 透過 make

1
arr := make([]int64,5)

3. 動態分配array

1
2
3
4
arr=make([][]int64,10) //外層有10格
for i:=0;i<10;i++{
arr[i]=make([]int64,i) //動態分裡面
}

array遍歷方法

1
2
3
4
5
6
7
for i := 0; i <len(a); i++ { 
fmt.Println("arr[", i, "] =", a[i])
}
// 用range, 第一個值 key為索引,value為索引的值
for key, value := range arr {
fmt.Println("arr[", i, "] =", value)
}

slice用法

新增slice方式

1. 使用array

1
2
var myArray [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var mySlice []int = myArray[:5]

2. 使用 make

1
2
3
4
5
// make([]T, length, capacity)
// 創建長度為5,容量為10的切片
slice1 := make([]int, 5, 10)
// 創建長度為5,並初始化該切片
slice2 := []int{1, 2, 3, 4, 5}

註: make的capacity若沒有設置會預設跟length一樣,為slice最大長度之上限。

動態新增slice長度: 使用append

1
2
3
4
// 在slice2 增加6
slice2 = append(slice2, 6)
fmt.Println("slice:", slice2)
// slice: 1 2 3 4 5 6

動態減少slice長度: slice[:]

例如:去除最前面一個元素

1
2
queue := []int{1,2,3}
queue = queue[1:] // queue = {2,3}

使用slcie實作一個簡單的queue結構

  • 宣告一個queue結構
1
queue := []int{}
  • 新增一個元素到queue
1
queue = append(queue, 6)
  • 從queue的開頭pop一個元素
1
2
element := queue[0]
queue = queue[1:]

檢查slice是否為空 len()

1
2
3
4
5
slice := []int{}

if (len(slice) == 0) {
...
}

slice 搭配 struct的傳值與回傳

以我做 Leetcode 111. Minimum Depth of Binary Tree 的範例來看,怎麼使用slice搭配struct進行傳值與回傳

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

type pair struct {
node *TreeNode
height int
}

func minDepth(root *TreeNode) int {
// 若目前root為nil 高度為0
if root == nil {
return 0
}

// 使用queue存放當前的root, 透過golang的slice來實作
queue := []pair{}

// make a new pair for root
rootPair := pair{node: root, height: 1}
queue = append(queue, rootPair)

for len(queue) != 0 {
element := queue[0]
elementNode := element.node
// 將取出來的elemenet去掉
queue = queue[1:]

// 如果左右子樹都還有值,那就繼續找,將left, right塞進queue
if elementNode.Left == nil && elementNode.Right == nil {
return element.height
}

if elementNode.Left != nil {
queue = push(queue, elementNode.Left, element.height)
}

if elementNode.Right != nil {
queue = push(queue, elementNode.Right, element.height)
}
}
return 0
}

func push(queue []pair, root *TreeNode, currHeight int) []pair {
newElement := pair{node: root, height: currHeight + 1}
newQueue := append(queue, newElement)
return newQueue
}

line 14: 宣告一個型態為pair的struct slice

line 42: 將struct slice傳入push(),並回傳之

Array 和 Slice差異

array slice
長度宣告後不可以變動 長度可以透過append()或slice[:]做變動
X slice為array的指標,若更動slice,也會更動到原本array的內容

如何避免Slice更動到原本Array?

方法 1 : make and Copy

先開一個新的空間,用make開好,用copy拷貝過去

1
2
3
arr:=[]int{1,2,3,4}
newSlice := make([]int, len(arr))
copy(newSlice, arr)

方法 2 : append

1
2
arr:=[]int{1,2,3,4}
newSlice = append([]int64(nil), arr[1:3]...) //一定要「…」

Map用法

建立一個 map 兩種方式

使用make

1
2
3
m := make(map[string]int)
// m["age"] = 16
m := map[string]int{}

回傳值, 和 map 是否存在
如果是不存在的 key , value = 0 , ok = false

1
value , ok := m["age"]

利用 range 取得 map 中所有的 key 和 value, 並列印

1
2
3
for key, value := range m {
fmt.Println("Key:", key, "Value:", value)
}

一次宣告多值

1
2
3
4
5
person := map[string]int{
"age" : 16,
"height" : 180,
"weight" : 6,
}

Reference