1. 程式人生 > >Go學習(3):分支迴圈

Go學習(3):分支迴圈

程式的流程控制結構一共有三種:順序結構,選擇結構,迴圈結構。

一、條件語句

1.1 If語句

語法格式:

if 布林表示式 {
   /* 在布林表示式為 true 時執行 */
}
if 布林表示式 {
   /* 在布林表示式為 true 時執行 */
} else {
  /* 在布林表示式為 false 時執行 */
}
if 布林表示式1 {
   /* 在布林表示式1為 true 時執行 */
} else if 布林表示式2{
   /* 在布林表示式1為 false ,布林表示式2為true時執行 */
} else{
   /* 在上面兩個布林表示式都為false時,執行*/
}

示例程式碼:

package main

import "fmt"

func main() {
   /* 定義區域性變數 */
   var a int = 10
 
   /* 使用 if 語句判斷布林表示式 */
   if a < 20 {
       /* 如果條件為 true 則執行以下語句 */
       fmt.Printf("a 小於 20\n" )
   }
   fmt.Printf("a 的值為 : %d\n", a)
}

如果其中包含一個可選的語句元件(在評估條件之前執行),則還有一個變體。它的語法是

if statement; condition {
}

示例程式碼:

package main

import (  
    "fmt"
)

func main() {  
    if num := 10; num % 2 == 0 { //checks if number is even
        fmt.Println(num,"is even") 
    }  else {
        fmt.Println(num,"is odd")
    }
}

需要注意的是,num的定義在if裡,那麼只能夠在該if…else語句塊中使用,否則編譯器會報錯的。

1.2 switch 語句

switch是一個條件語句,它計算表示式並將其與可能匹配的列表進行比較,並根據匹配執行程式碼塊。它可以被認為是一種慣用的方式來寫多個if else子句。

switch 語句用於基於不同條件執行不同動作,每一個 case 分支都是唯一的,從上直下逐一測試,直到匹配為止。
switch 語句執行的過程從上至下,直到找到匹配項,匹配項後面也不需要再加break。

而如果switch沒有表示式,它會匹配true

Go裡面switch預設相當於每個case最後帶有break,匹配成功後不會自動向下執行其他case,而是跳出整個switch, 但是可以使用fallthrough強制執行後面的case程式碼。

變數 var1 可以是任何型別,而 val1 和 val2 則可以是同類型的任意值。型別不被侷限於常量或整數,但必須是相同的型別;或者最終結果為相同型別的表示式。
您可以同時測試多個可能符合條件的值,使用逗號分割它們,例如:case val1, val2, val3。

switch var1 {
    case val1:
        ...
    case val2:
        ...
    default:
        ...
}

示例程式碼:

package main

import "fmt"

func main() {
   /* 定義區域性變數 */
   var grade string = "B"
   var marks int = 90

   switch marks {
      case 90: grade = "A"
      case 80: grade = "B"
      case 50,60,70 : grade = "C"  //case 後可以由多個數值
      default: grade = "D"  
   }

   switch {
      case grade == "A" :
         fmt.Printf("優秀!\n" )     
      case grade == "B", grade == "C" :
         fmt.Printf("良好\n" )      
      case grade == "D" :
         fmt.Printf("及格\n" )      
      case grade == "F":
         fmt.Printf("不及格\n" )
      default:
         fmt.Printf("差\n" );
   }
   fmt.Printf("你的等級是 %s\n", grade );      
}

如需貫通後續的case,就新增fallthrough

package main

import (
	"fmt"
)

type data [2]int

func main() {
	switch x := 5; x {
	default:
		fmt.Println(x)
	case 5:
		x += 10
		fmt.Println(x)
		fallthrough
	case 6:
		x += 20
		fmt.Println(x)

	}

}

結果

15
35

case中的表示式是可選的,可以省略。如果該表示式被省略,則被認為是switch true,並且每個case表示式都被計算為true,並執行相應的程式碼塊。

示例程式碼:

package main

import (  
    "fmt"
)

func main() {  
    num := 75
    switch { // expression is omitted
    case num >= 0 && num <= 50:
        fmt.Println("num is greater than 0 and less than 50")
    case num >= 51 && num <= 100:
        fmt.Println("num is greater than 51 and less than 100")
    case num >= 101:
        fmt.Println("num is greater than 100")
    }

}

switch的注意事項

  1. case後的常量值不能重複
  2. case後可以有多個常量值
  3. fallthrough應該是某個case的最後一行。如果它出現在中間的某個地方,編譯器就會丟擲錯誤。

Type Switch

switch 語句還可以被用於 type-switch 來判斷某個 interface 變數中實際儲存的變數型別。

switch x.(type){
    case type:
       statement(s);      
    case type:
       statement(s); 
    /* 你可以定義任意個數的case */
    default: /* 可選 */
       statement(s);
}
package main

import "fmt"

func main() {
   var x interface{}
     
   switch i := x.(type) {
      case nil:	  
         fmt.Printf(" x 的型別 :%T",i)                
      case int:	  
         fmt.Printf("x 是 int 型")                       
      case float64:
         fmt.Printf("x 是 float64 型")           
      case func(int) float64:
         fmt.Printf("x 是 func(int) 型")                      
      case bool, string:
         fmt.Printf("x 是 bool 或 string 型" )       
      default:
         fmt.Printf("未知型")     
   }   
}

結果

x 的型別 :<nil>

1.3 select 語句

select 語句類似於 switch 語句,但是select會隨機執行一個可執行的case。如果沒有case可執行,它將阻塞,直到有case可執行。

package main

import "fmt"

func main() {
   var c1, c2, c3 chan int
   var i1, i2 int
   select {
      case i1 = <-c1:
         fmt.Printf("received ", i1, " from c1\n")
      case c2 <- i2:
         fmt.Printf("sent ", i2, " to c2\n")
      case i3, ok := (<-c3):  // same as: i3, ok := <-c3
         if ok {
            fmt.Printf("received ", i3, " from c3\n")
         } else {
            fmt.Printf("c3 is closed\n")
         }
      default:
         fmt.Printf("no communication\n")
   }    
}

執行結果:

no communication
  • 每個case都必須是一個通訊

  • 所有channel表示式都會被求值

  • 所有被髮送的表示式都會被求值

  • 如果任意某個通訊可以進行,它就執行;其他被忽略。

  • 如果有多個case都可以執行,Select會隨機公平地選出一個執行。其他不會執行。

  • 否則:

    如果有default子句,則執行該語句。

    如果沒有default字句,select將阻塞,直到某個通訊可以執行;Go不會重新對channel或值進行求值。

二、迴圈語句

迴圈語句表示條件滿足,可以反覆的執行某段程式碼。

for是唯一的迴圈語句。(Go沒有while迴圈)

2.1 For語句

語法結構:

for init; condition; post { }

初始化語句只執行一次。在初始化迴圈之後,將檢查該條件。如果條件計算為true,那麼{}中的迴圈體將被執行,然後是post語句。post語句將在迴圈的每次成功迭代之後執行。在執行post語句之後,該條件將被重新檢查。如果它是正確的,迴圈將繼續執行,否則迴圈終止。

示例程式碼:

package main

import (  
    "fmt"
)

func main() {  
    for i := 1; i <= 10; i++ {
        fmt.Printf(" %d",i)
    }
}

在for迴圈中宣告的變數僅在迴圈範圍內可用。因此,i不能在外部訪問迴圈。

所有的三個組成部分,即初始化、條件和post都是可選的。

for condition { }

效果與while相似

for { }

效果與for(;;) 一樣

for 迴圈的 range 格式可以對 slice、map、陣列、字串等進行迭代迴圈

for key, value := range oldMap {
    newMap[key] = value
}
package main

import "fmt"

func main() {

   var b int = 15
   var a int

   numbers := [6]int{1, 2, 3, 5} 

   /* for 迴圈 */
   for a := 0; a < 10; a++ {
      fmt.Printf("a 的值為: %d\n", a)
   }

   for a < b {
      a++
      fmt.Printf("a 的值為: %d\n", a)
      }

   for i,x:= range numbers {
      fmt.Printf("第 %d 位 x 的值 = %d\n", i,x)
   }   
}

執行結果:

a 的值為: 0
a 的值為: 1
a 的值為: 2
a 的值為: 3
a 的值為: 4
a 的值為: 5
a 的值為: 6
a 的值為: 7
a 的值為: 8
a 的值為: 9
a 的值為: 1
a 的值為: 2
a 的值為: 3
a 的值為: 4
a 的值為: 5
a 的值為: 6
a 的值為: 7
a 的值為: 8
a 的值為: 9
a 的值為: 10
a 的值為: 11
a 的值為: 12
a 的值為: 13
a 的值為: 14
a 的值為: 150 位 x 的值 = 11 位 x 的值 = 22 位 x 的值 = 33 位 x 的值 = 54 位 x 的值 = 05 位 x 的值 = 0

2.2 跳出迴圈的語句

2.2.1 break語句

break:跳出迴圈體。break語句用於在結束其正常執行之前突然終止for迴圈

示例程式碼:

package main

import (  
    "fmt"
)

func main() {  
    for i := 1; i <= 10; i++ {
        if i > 5 {
            break //loop is terminated if i > 5
        }
        fmt.Printf("%d ", i)
    }
    fmt.Printf("\nline after for loop")
}

2.2.2 continue語句

continue:跳出一次迴圈。continue語句用於跳過for迴圈的當前迭代。在continue語句後面的for迴圈中的所有程式碼將不會在當前迭代中執行。迴圈將繼續到下一個迭代。

示例程式碼:

package main

import (  
    "fmt"
)

func main() {  
    for i := 1; i <= 10; i++ {
        if i%2 == 0 {
            continue
        }
        fmt.Printf("%d ", i)
    }
}

2.2.3 goto語句

goto:可以無條件地轉移到過程中指定的行

package main

import "fmt"

func main() {
   /* 定義區域性變數 */
   var a int = 10

   /* 迴圈 */
   LOOP: for a < 20 {
      if a == 15 {
         /* 跳過迭代 */
         a = a + 1
         goto LOOP
      }
      fmt.Printf("a的值為 : %d\n", a)
      a++     
   }  
}