PJCHENder 未整理筆記

[Golang] 流程控制 Control Flow

2020-06-04

[Golang] 流程控制 Control Flow

For Loop

基本使用

最基本的 for 迴圈會包含三個部分:

  • 起始句(init statement):可省略,在第一次疊代前會執行
  • 條件式(condition expression):在下次執行疊代中的程式碼前會評估
  • post statement:可省略,在每次執行完疊代中的程式碼後會執行
1
2
3
for i := 0; i < 10; i++ {
fmt.Println(i)
}

while

主要把 for 的 init statement 和 post statement 省略後,就會變成 while 語句:

1
2
3
4
5
6
7
8
// init statement 和 post statement 可以省略,就會變成 while 語句
func main() {
i := 0
for i < 10 {
fmt.Println(i)
i++
}
}

infinite loop

把 for 後面所有參數都移除,就變成 infinite loop:

1
2
3
for {
fmt.Println("Don't do this")
}

If

基本使用

1
2
3
4
5
6
7
8
func main() {
i := 10
if i < 5 {
fmt.Println(i, "is smaller than 5")
} else {
fmt.Println(i, "is equal and larger than 5")
}
}

搭配 statement 使用

iffor 類似,都可以在最前面加上 statement,它會在 if 中的程式執行前被執行;若在 statement 中宣告變數,則這個變數只能在 if 的 block 中被使用(包含 else):

1
2
3
4
5
6
// if <statement>; <condition> {...}
if i := 3; i < 5 {
fmt.Println(i, "is smaller than 5")
} else {
fmt.Println(i, "is equal or larger than 5")
}

switch

  • 在 Go 的 switch 中不需要使用 break(Go 執行時會自動 break)
  • switchif, for 類似,在最前面都可以加上 statement
  • 從上往下開始判斷每一個 case,並在配對到的 case 後終止

基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func main() {
fmt.Print("Go runs on ")

// 等同於
// os := runtime.GOOS
// switch os {
switch os := runtime.GOOS; os {
case "darwin":
fmt.Println("OS X.")
case "linux":
fmt.Println("Linux.")
default:
fmt.Printf("%s.\n", os)
}
}

case 後面可以是 express

case 後面不一定一定要是字串,是可以放 express 的:

1
2
3
4
5
6
7
8
9
10
11
func main() {
num := 1
switch start := 0; num {
case start:
fmt.Println("0")
case start + 1:
fmt.Println("1")
default:
fmt.Println("other")
}
}

switch 後可以不帶變數(可用來簡化 if … else)

switch 可以不帶變數,直接變成 if...elseif...else 的簡化版:

1
2
3
4
5
6
7
8
9
10
11
func main() {
currentHour := time.Now().Hour()
switch {
case currentHour < 12:
fmt.Println("Good morning!")
case currentHour < 17:
fmt.Println("Good afternoon.")
default:
fmt.Println("Good eventing")
}
}

判斷 interface 被 implement 的型別

建立 interface 後可以使用 interface.(type) 來判斷該 interface 被 implement 的型別:

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
var (
i interface{}
)

func convert(i interface{}) {
switch t := i.(type) {
case int:
fmt.Printf("%v is integer(%T)\n", t, t)
case string:
fmt.Printf("%v is string(%T)\n", t, t)
case float64:
fmt.Printf("%v is float64(%T)\n", t, t)
default:
fmt.Printf("type not found")
}
}

func main() {
convert(100) // 100 is integer(int)

convert(45.55) // 45.55 is float64(float64)

convert("foo") // foo is string(string)

convert(float32(10.0)) // type not found
}

defer

Defer, Panic, and Recover @ Golang Blog

defer 這個 statement 可以用來在函式最終要回傳前被執行,但要留意的是,這個 defer 中所使用到的參數是在執行到的時候就已經被帶入:

1
2
3
4
5
6
7
8
9
func main() {
language := "Go"
defer fmt.Print(language + "\n")

language = "Node.js"
fmt.Print("Hello ")
}

// 輸出:Hello Go

當有多個 defer 時,採用的是 後進先出(last-in-first-out) 原則:

1
2
3
4
5
6
7
8
9
10
func main() {
language := "Go"
defer fmt.Print(" to " + language + "\n")

language = "Node.js"
defer fmt.Print("from " + language)
fmt.Print("Hello ")
}

// 輸出:Hello from Node.js to Go

Iterate

1
2
3
4
5
6
7
cardValues := []string{"Ace", "Two", "Three", "Four"}

// 如果只需要 index,可以簡寫成:
// for i := range cardValues { ... }
for i, value := range cardValues {
fmt.Println(i, value)
}

參考

Tags: Go

掃描二維條碼,分享此文章