[A Tour of Go 學習筆記] 06 Range、Map 和 function
使用官方教學瞭解 Go Range、Map 和 function
初入 Golang 的世界,首先我們使用官方教學:A Tour of Go
來認識基本的 Golang 使用
這篇介紹 Range、Map 和 function
Range
用 for 迴圈的range
形式可以遍歷切片或是 map,類似於其他語言的 foreach 用法
當使用 for 迴圈遍歷切片的時候,每次迭代都會回傳兩個值。第一個值是元素的 index,第二個值是元素內容的副本。
package main
import "fmt"
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
func main() {
for i, v := range pow {
fmt.Printf("2**%d = %d\n", i, v)
}
}
/*
>>> 2**0 = 1
>>> 2**1 = 2
>>> 2**2 = 4
>>> 2**3 = 8
>>> 2**4 = 16
>>> 2**5 = 32
>>> 2**6 = 64
>>> 2**7 = 128
*/
如果不需要某個值(通常是 index)可以用_
來忽略他
因為 golang 對定義卻沒用的變數很在意,會出錯誤:key declared but not used
for i, _ := range pow
for _, value := range pow
如果只需要 index,可以直接忽略第二個變數
for i := range pow
底下是一個只取 index 的範例:
package main
import "fmt"
func main() {
pow := make([]int, 10)
for i := range pow {
pow[i] = 1 << uint(i) // 把值設為 index 左移一位元,等於 2 的 i 次方
}
for _, value := range pow {
fmt.Printf("%d\n", value)
}
}
/*
>>> 1
>>> 2
>>> 4
>>> 8
>>> 16
>>> 32
>>> 64
>>> 128
>>> 256
>>> 512
*/
Map
前面介紹的不管是陣列或是切片,都是以數字當 index,而 map 可以使用字串作為 index
用在Key-Value
的組合
在初始化沒有賦值時 map 的初始值(zero value)是nil
,一個nil
map 沒有 key 也不能加入 key
使用make
函數可以初始化指定型別 map 並回傳
package main
import "fmt"
type Vertex struct {
Lat, Long float64
}
var m map[string]Vertex
func main() {
m = make(map[string]Vertex)
m["Bell Labs"] = Vertex{
40.68433, -74.39967,
}
fmt.Println(m["Bell Labs"])
}
/*
>>> {40.68433 -74.39967}
*/
map 和 struct 類似,但是 key 是必須的
package main
import "fmt"
type Vertex struct {
Lat, Long float64
}
var m = map[string]Vertex{
"Bell Labs": {40.68433, -74.39967},
"Google": {37.42202, -122.08408},
}
func main() {
fmt.Println(m)
}
/*
>>> map[Bell Labs:{40.68433 -74.39967} Google:{37.42202 -122.08408}]
*/
如果最頂層的型別只是一種類別名稱,則可以省略不寫
package main
import "fmt"
type Vertex struct {
Lat, Long float64
}
var m = map[string]Vertex{
"Bell Labs": {40.68433, -74.39967},
"Google": {37.42202, -122.08408},
}
func main() {
fmt.Println(m)
}
/*
>>> map[Bell Labs:{40.68433 -74.39967} Google:{37.42202 -122.08408}]
*/
修改 map 中的值
在 map 中插入或修改元素
m[key] = elem
取得元素
elem = m[key]
刪除元素
delete(m, key)
透過雙賦值(two-value assignment)檢查某個鍵值是否存在
elem, ok = m[key]
如果 key 存在 m 中ok = true
,否則ok = false
若讀取不存在的鍵值時,會得到 map 的元素類型的預設值
在使用時若elem
或是ok
還沒被定義,可以使用:
做簡短變數聲明
elem, ok := m[key]
實際操作起來就:
package main
import "fmt"
func main() {
m := make(map[string]int)
m["Answer"] = 42
fmt.Println("The value:", m["Answer"])
m["Answer"] = 48
fmt.Println("The value:", m["Answer"])
delete(m, "Answer")
fmt.Println("The value:", m["Answer"])
v, ok := m["Answer"]
fmt.Println("The value:", v, "Present?", ok)
}
/*
>>> The value: 42
>>> The value: 48
>>> The value: 0
>>> The value: 0 Present? false
*/
函數 Function
Function values
function 也是值,也可以被傳遞
函數可以作為函數的參數或是回傳值
package main
import (
"fmt"
"math"
)
func compute(fn func(float64, float64) float64) float64 {
return fn(3, 4)
}
func main() {
hypot := func(x, y float64) float64 {
return math.Sqrt(x*x + y*y)
}
fmt.Println(hypot(5, 12))
fmt.Println(compute(hypot))
fmt.Println(compute(math.Pow))
}
/*
>>> 13
>>> 5
>>> 81
*/
閉包 Function closures
Go function 也可以是一個閉包
閉包是一個函數值,引用了函數本身外部的變數。閉包函數被指定給變數,並且可以存取變數。
換句話說,閉包函數跟變數被「綁定」在一起。
範例中的adder
這個 function 回傳一個閉包,所以每個sum
變數都擁有自己的閉包函數
package main
import "fmt"
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
func main() {
pos, neg := adder(), adder()
for i := 0; i < 10; i++ {
fmt.Println(
pos(i),
neg(-2*i),
)
}
}
/*
>>> 0 0
>>> 1 -2
>>> 3 -6
>>> 6 -12
>>> 10 -20
>>> 15 -30
>>> 21 -42
>>> 28 -56
>>> 36 -72
>>> 45 -90
*/