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的注意事項
- case後的常量值不能重複
- case後可以有多個常量值
- 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 的值為: 15
第 0 位 x 的值 = 1
第 1 位 x 的值 = 2
第 2 位 x 的值 = 3
第 3 位 x 的值 = 5
第 4 位 x 的值 = 0
第 5 位 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++
}
}