延續(一)的內容, 討論Go的資料結構
對Go來說, array就是一個有特定長度的元素的有號序列。
[n]T
type 就是一個有n個 T type值的陣列。 陣列的長度是其型別的一部份, 所以陣列item值可以改變, 但陣列長度是不能變動的
以下宣告了一個長度為5, type為int的陣列, 注意陣列元素的初始值為0, 利用內建函式len
傳回陣列長度:
var a [5]int
a[5] = 100
fmt.Println(a)
fmt.Println(a[5])
fmt.Println(len(a))
會印出:
[0 0 0 0 100]
100
5
也可以直接宣告並且初始陣列:
b := [5]int{1, 2, 3, 4, 5}
懶得填陣列長度或是懶得算, 也可以用...
代替:
b := [...]int{1, 2, 3, 4, 5}
Slice像是功能更強大的array, array長度不能變動, slice可以。
Slice長的就像array, 只是沒有宣告其長度。[]T
就是有型別為T的元素slice:
var s []string
這樣會建立一個長度為0, 容量為0的slice。這個slice的值為nil
。
要建立一個非0長度的slice(元素初始值均為zero-value), 要利用Go內建的make
:
s := make([]string, 3)
fmt.Println(s)
會得到以下結果(string的zero-value是一個空白字元):
[ ]
也可以限制slice的容量(capcity):
b := make([]int, 0, 5) // len(b)=0, cap(b)=5
如果沒有宣告容量, slice的容量等於長度。例如上上個例子make([]string, 3)
這個slice的容量也為3。
操作方法都跟array一樣。
只是slice多了許多好用的操作, 例如append
:
s = append(s, "d", "e")
fmt.Println(s)
會得到:
[ de]
既然叫作Slice, 那代表Slice有一個slice
operator 來讓我們將現有的slice切片(像Python語法), 使用 slice[low: high]
:
i := s[2:5]
i = s[:5]
i = s[2:]
s[2:]
表示建立一個s的sub-slice, 這個sub-slice是s的第2個字元到最後一個字元。
slice也可以直接宣告初始值:
l := []string{"a", "b", "c"}
宣告一個新的slice, 可以利用copy
來做拷貝:
j := make([]string,3)
copy(j, s)
如果j的長度小於s的長度, j就只會拷貝j長度的s, 若j長度大於s, 那多的部份就是初始為zero-value。
Map就是 key-value配對, 就是其他程式語言的hashes
或是 dicts
。
要建立一個空的map, 就要使用make
--> make(male[key-type]val-type) 像這樣:
m := make(map[string]int)
m["k1"] = 7
m["k2"] = 14
fmt.Println(m)
fmt.Println(len(m))
結果為:
map[k1:7 k2:14]
2
也可以直接宣告並給定初始值:
n := map[string]int{"foo": 1, "bar": 2}
利用內建的delete
刪除key/value:
delete(m, "k2")
事實上當我們從map取值的時候, return value有兩個, 第一個是value, 第二個是boolean,
例如繼承上例, 我們把k2的key-value從m中刪除了, 那麼 :
a, b := m["k1"]
c, d := m["k2"]
fmt.Println(a, b)
fmt.Println(c, d)
會得到:
2 true
0 false
Go在找map找不到符合的key的時候,會傳回zero value, 像是0
或是""
, 不過我們拿到zero value沒啥意義, 這時候我們可以忽略使用 blank identifier _ 來忽略這個傳回值:
_, d := m["k2"]
fmt.Println(d)
for
加上 range
iterator 可以幫助我們遍歷(browse)我們上面所提到的資料結構內的元素。
nums := []int{1, 2, 3, 4}
for index, num := range nums {
fmt.Println(index, num)
}
如果不需要index, 那麼就使用 blank identifier 將index忽略掉:
nums := []int{1, 2, 3, 4}
for _, num := range nums {
fmt.Println(num)
}
如果只要index, 那就把index後面逗號的全拿掉:
nums := []int{1, 2, 3, 4}
for index := range nums {
fmt.Println(index)
}
如果map的value是struct type:
type Vertex struct {
Lat, Long float64
}
var m = map[string]Vertex{
"Bell Labs": Vertex{
40.1212, -74.123123,
},
"Google": Vertex{
37.213213, -123.213213,
},
}
也可以把value的type省略不寫:
type Vertex struct {
Lat, Long float64
}
var m = map[string]Vertex{
"Bell Labs": {40.1212, -74.123123},
"Google": {37.213213, -123.213213}, //注意最後一個結尾還是要逗號
}
要刪除一個map的element使用delete
, 利用第二個參數ok
來測試是否該元素存在, 若ok傳回true:
delete(m, "Google")
fmt.Println(m)
v, ok := m["Google"]
fmt.Println("The value:", v, "Present?", ok)
range on map :
k := map[string]string{"a":"apple", "b":"banana"}
for key, value := range k{
fmt.Println(key, value)
}
注意如果是range on string, 那value將會是unicode code, index是開始的byte的index, 例如:
for index, value := range "你好go hello" {
fmt.PrintLn(index, value)
}
仔細觀察一下結果:
0 20320
3 22909
6 103
7 111
8 32
9 104
10 101
11 108
12 108
13 111
官網 Go Slices: usage and internals
An introduction to programming in Go