1. 程式人生 > 實用技巧 >A tour of Go (2) - Go語言運算子&流程控制

A tour of Go (2) - Go語言運算子&流程控制

Thursday, December 17, 2020

A tour of Go (2) - Go語言運算子&流程控制

1. Go語言運算子

不需要匯入包

  • 算數運算子:+, -, *, /, %, ++, --
  • 關係運算符:==, !=, >, <, >=, <=
  • 邏輯運算子:&&, ||, !
  • 位運算子:& 相與, | 相或, ^ 異或, << 左移n位(乘以2的n次方), >> 右移n位
  • 賦值運算子:=, +=, -=, *=, /=, %=, <<=, >>=, &=, ^=, |=
  • 其他運算子& 返回變數儲存地址, * 指標變數
func main() {
   var a int = 4
   var ptr *int	// 宣告指標變數
   ptr = &a	// 將變數地址賦值給指標變數
   println("a的值為", a);    // 4
   println("*ptr為", *ptr);  // 4,*指標變數 -> 取得地址對應的變數值 
   println("ptr為", ptr);    // 824633794744 直接取得變數儲存地址
}

2. 流程控制語句 —— for 迴圈

Go 只有一種迴圈結構:for 迴圈。

基本的 for

迴圈由三部分組成,它們用分號隔開:

  • 初始化語句:在第一次迭代前執行 e.g., i := 0
  • 條件表示式:在每次迭代前求值 e.g., i < 10
  • 後置語句:在每次迭代的結尾執行 e.g., i++
for i := 0; i < 10; i++ {
    sum += i
}

初始化語句通常為一句短變數宣告,該變數宣告僅在 for 語句的作用域中可見

注意:和其他語言不同,Go 的 for 語句後面的三個構成部分外沒有小括號大括號 { } 則是必須的。

初始化語句和後置語句是可選的,而條件表示式必須宣告。

sum := 1
for ; sum < 1000; {
    sum += sum
}

此時你可以去掉分號,因為 C 的 while 在 Go 中叫做 for

sum := 1
for sum < 1000 { // 此時等價於C語言中的while
    sum += sum
}

如果省略迴圈條件,就會變成無限迴圈

3. 流程控制語句 —— if 條件

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

if x < 0 {
    return x
}

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

該語句宣告的變數作用域僅在 if 之內。

if v := math.Pow(x, n); v < lim { // 可以在條件表示前執行一個語句,如變數短賦值
		return v
	}

if 的簡短語句中宣告的變數同樣可以在任何對應的 else 塊中使用。

4. 流程控制語句 —— switch 條件

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

Go 只執行選定的 case,而非之後所有的 case。 實際上,Go 自動提供了在這些語言中每個 case 後面所需的 break 語句。

如果執行的 case 帶有 fallthrough,程式會繼續執行下一條 case,且它不會去判斷下一個 case 的表示式是否為 true。直到遇見不帶 fallthroughcase 或執行完全部 casedefault,程式停止。

Go 的另一點重要的不同在於 switchcase 無需為常量,且取值不必為整數

沒有條件的 switchswitch true 一樣。這種形式能將一長串的 if-then-else 寫得更加清晰

t := time.Now() // 將不同的判斷條件寫在 case 條件處,代替一長串的 if-then-else
	switch {
	case t.Hour() < 12:
		fmt.Println("Good morning!")
	case t.Hour() < 17:
		fmt.Println("Good afternoon.")
	default:
		fmt.Println("Good evening.")
	}

5. 流程控制語句 —— defer 推遲執行

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

推遲呼叫的函式其引數會立即求值,但直到外層函式返回前該函式都不會被呼叫

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

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

func main() { // 結果:counting, done, 9, 8, ..., 0
	fmt.Println("counting")
	for i := 0; i < 10; i++ {
		defer fmt.Println(i)
	}
	fmt.Println("done")
}