Go語言入門 (Day 2) 流程控制語句

Go 流程控制語句:for、if、else、switch 和 defer

§ for

Go 只有一種循環結構:for 循環。

基本的 for 循環由三部分組成,它們用分號隔開:

  • 初始化語句:在第一次迭代前執行
  • 條件表達式,則前後的;會被去掉,若有:在每次迭代前求值
  • 後置語句:在每次迭代的結尾執行

初始化語句通常爲一句短變量聲明,該變量聲明僅在 for 語句的作用域中可見。

一旦條件表達式的布爾值爲 false,循環迭代就會終止。

注意:和 C、Java、JavaScript 之類的語言不同,Go 的 for 語句後面的三個構成部分外沒有小括號 ( ), 而大括號 { } 則是必須的。

package main

import "fmt"

func main() {
	sum := 0
	for i := 0; i < 10; i++ {
		sum += i
	}
	fmt.Println(sum)
}

輸出:

45

初始化語句和後置語句是可選的,例如:

package main

import "fmt"

func main() {
	i := 0
	j := 100
	c := 0
	for i != j {    // for ;i != j; { 自動格式化後的結果,go 中的"while"
		i++
		j--
		c += 1
	}
	fmt.Printf("i: %v, j: %v, c: %v\n", i, j, c)
}

輸出:

i: 50, j: 50, c: 50

如果只有條件表達式,則前後的 ; 會被 go fmt 去掉,成爲 go 中的"while"。若有初始化語句、條件表達式、後置語句中的兩個,則不會被省略。

for 也是 go 的 “while”

可以去掉分號,在 for{ 只寫條件語句。
C 的 while 在 Go 中也叫做 for

package main

import "fmt"

func main() {
	s := 1
	for s <= 1000 {
		s += s
	}
	fmt.Println(s)
}

輸出:

1024

無限循環

如果省略循環條件,for{ 間什麼都不寫,該循環就不會結束,因此無限循環可以寫得很緊湊。
(沒有條件的 for 同 for true 一樣。)

package main

import (
	"fmt"
	"time"
)

func main() {
	i := 0
	for {
		fmt.Println(i)
		i++
		time.Sleep(100 * time.Millisecond)  // 暫停100毫米
	}
}

輸出:

0
1
2
...     // 省去部分輸出
^Csignal: interrupt     // 鍵入了 control+C,以終止程序

§ if

Go 的 if 語句與 for 循環類似,表達式外無需小括號 ( ) ,而大括號 { } 則是必須的。

package main

import (
	"fmt"
	"math"
)

func sqrt(x float64) string {
	if x < 0 {
		return sqrt(-x) + "i"
	}
	return fmt.Sprint(math.Sqrt(x))
}

func main() {
	fmt.Println(sqrt(2), sqrt(-4))
}

輸出:

1.4142135623730951 2i

if 的簡短語句

for 一樣, if 語句可以在條件表達式前執行一個簡單的語句。

該語句聲明的變量作用域僅在 if 之內。

(在最後的 return 語句處使用 v 看看。)

package main

import (
	"fmt"
	"math"
)

func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	}
	return lim
}

func main() {
	fmt.Println(
		pow(3, 2, 10),
		pow(3, 3, 20),
	)
}

輸出:

9 20

if-else

package main

import (
	"fmt"
	"math"
)

func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	} else {
		fmt.Printf("%g >= %g\n", v, lim)
	}
	// 這裏開始就不能使用 v 了
	return lim
}

func main() {
	fmt.Println(
		pow(3, 2, 10),
		pow(3, 3, 20),
	)
}

輸出:

27 >= 20
9 20

if 的簡短語句中聲明的變量同樣可以在任何對應的 else 塊中使用。

(在 mainfmt.Println 調用開始前,兩次對 pow 的調用均已執行並返回其各自的結果。)

§ switch

switch 是編寫一連串 if - else 語句的簡便方法。它運行第一個值等於條件表達式的 case 語句。

Go 的 switch 語句類似於 C、C++、Java、JavaScript 和 PHP 中的,不過 Go 只運行選定的 case,而非之後所有的 case。 實際上,Go 自動提供了在這些語言中每個 case 後面所需的 break 語句。 除非以 fallthrough 語句結束,否則分支會自動終止。 Go 的另一點重要的不同在於 switchcase 無需爲常量,且取值不必爲整數。

package main

import (
	"fmt"
	"runtime"
)

func main() {
	fmt.Print("Go runs on ")
	switch os := runtime.GOOS; os {
	case "darwin":
		fmt.Println("OS X.")
	case "linux":
		fmt.Println("Linux.")
	default:
		// freebsd, openbsd,
		// plan9, windows...
		fmt.Printf("%s.\n", os)
	}
}

輸出:

Go runs on OS X.

switch 的求值順序

switchcase 語句從上到下順次執行,直到匹配成功時停止。

(例如,

switch i {
case 0:
case f():
}

在 i==0 時 f 不會被調用。)

package main

import (
	"fmt"
	"time"
)

func main() {
	fmt.Println("When's Saturday?")
	today := time.Now().Weekday()
	switch time.Saturday {
	case today + 0:
		fmt.Println("Today.")
	case today + 1:
		fmt.Println("Tomorrow.")
	case today + 2:
		fmt.Println("In two days.")
	default:
		fmt.Println("Too far away.")
	}
}

輸出:

When's Saturday?
Tomorrow.

沒有條件的 switch

沒有條件的 switchswitch true 一樣。

這種形式能將一長串 if-then-else 寫得更加清晰。

package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Now()
	switch {
	case t.Hour() < 12:
		fmt.Println("Good morning!")
	case t.Hour() < 17:
		fmt.Println("Good afternoon.")
	default:
		fmt.Println("Good evening.")
	}
}

輸出:

Good evening.

§ defer

defer 語句會將函數推遲到外層函數返回之後執行。

推遲調用的函數其參數會立即求值(閉包?🤔️),但直到外層函數返回前該函數都不會被調用。

package main

import "fmt"

func main() {
	defer fmt.Println("world")

	fmt.Println("hello")
}

輸出:

hello
world

defer 棧

推遲的函數調用會被壓入一個棧中。當外層函數返回時,被推遲的函數會按照後進先出的順序調用。

更多關於 defer 語句的信息,參考閱讀此文

package main

import "fmt"

func main() {
	fmt.Println("counting...")

	for i := 0; i < 10; i++ {
		defer fmt.Println(i)
	}

	fmt.Println("done.")
}

輸出:

counting...
done.
9
8
7
6
5
4
3
2
1
0
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章