05 Golang 流程控制

一、条件判断

1. 条件判断简介

条件语句是用来判断给定的条件是否满足(表达式值是否为true或者false),并根据判断的结果决定执行情况的语句。go语言中的条件语句主要包含如下几种情况:

  • if - else if - else 语句:if 语句由一个布尔表达式后紧跟一个或多个语句组成,语句后可以使用可选的 elseelse if 语句, 这些语句中的表达式在布尔表达式的值和 if 语句后布尔表达式的值不同时执行;可以在 ifelse if 语句中嵌入一个或多个 ifelse if 语句。

  • switch 语句: switch 语句用于基于不同条件执行不同动作。

  • select 语句: select 语句类似于 switch 语句,但是 select 会随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。

在 go 语言中使用 if 时需要注意以下几点:

  • 不需使用括号将条件包含起来。

  • 大括号{}必须存在,即使只有一行语句。

  • 左括号必须在ifelse的同一行。

  • if之后,条件语句之前,可以添加变量初始化语句,使用进行分隔。

在 go 语言中使用 switch 时需要注意以下几点:

  • 支持多条件匹配。

  • 不同的 case 之间不使用 break 分隔,默认只会执行一个 case

  • 如果想要执行多个 case,需要使用 fallthrough 关键字,也可用 break 终止。

  • 分支还可以使用表达式。

2. if 语句的使用

2.1 if 语句

go语言中 if 语句的语法如下:

1 // 当表达式1的结果为true时,执行分支1,否则判断表达式2,如果满足则执行分支2,都不满足时,则执行分支3
2 if 表达式1 {
3     分支1
4 } else if 表达式2 {
5     分支2
6 } else{
7     分支3
8 }

示例1:满足条件则执行,否则跳过。

 1 package main
 2  3 import "fmt"
 4  5 func main() {
 6  7     age := 20
 8  9     if age >= 18 {
10         fmt.Println("你已经成年了")
11     }
12 13     fmt.Printf("程序运行结束")
14 }

示例2:初始变量可以声明在布尔表达式里面,但是只在判断中生效。

 1 package main
 2  3 import "fmt"
 4  5 func main() {
 6     if age := 20; age >= 18 {
 7         fmt.Println("你已经成年了")
 8     }
 9 10     fmt.Printf("程序运行结束")
11 12     fmt.Println(age)  // undefined: age
13 }

示例3:不能使用0或非0表示真假。

 1 package main
 2  3 import "fmt"
 4  5 func main() {
 6     var i = 1
 7     if i {       // 编译失败
 8         fmt.Println("here")
 9     }
10     fmt.Printf("程序运行结束")
11 }

2.2 if-else 语句

go语言中 if-else 语句的语法如下:

1 if 布尔表达式 {
2    /* 在布尔表达式为 true 时执行 */
3 } else {
4   /* 在布尔表达式为 false 时执行 */
5 }

示例1:判断奇数偶数。

 1 package main
 2  3 import (
 4     "fmt"
 5 )
 6  7 func main() {
 8     var num int
 9 10     fmt.Println("输入一个数字:")
11     fmt.Scan(&num)
12     fmt.Printf("s 的值是:%v \n", num)
13 14     if num%2 == 0 {
15         fmt.Println("偶数")
16     } else {
17         fmt.Print("奇数")
18     }
19 }

示例2:判断是否成年。

 1 package main
 2  3 import (
 4     "fmt"
 5     "math/rand"
 6     "time"
 7 )
 8  9 func main() {
10     // 生成一个 1~100 随机数
11     rand.Seed(time.Now().UnixNano())
12     age := rand.Intn(100)
13 14     if age >= 18 {
15         fmt.Println("你已经成年")
16     } else {
17         fmt.Println("你还未成年")
18     }
19 }

示例3:初始变量可以声明在布尔表达式里面,但是只在判断中生效。

 1 package main
 2  3 import (
 4     "fmt"
 5     "math/rand"
 6     "time"
 7 )
 8  9 func main() {
10     // 生成一个 1~100 随机数
11     rand.Seed(time.Now().UnixNano())
12 13     if age := rand.Intn(100); age >= 18 {
14         fmt.Println("你是成年人")
15     } else {
16         fmt.Println("你还未成年")
17     }
18 19     //fmt.Println(age)  age 作用域只在布尔表达式中
20 }

2.3 if-else if-else 语句

go语言中 if-else if-else 语句的语法如下:

1 if 布尔表达式1 {
2     // do something
3 } else if 布尔表达式2 {
4     // do something else
5 }else {
6     // catch-all or default
7 }

示例1:根据分数划分等级

 1 package main
 2 
 3 import (
 4     "fmt"
 5     "math/rand"
 6     "time"
 7 )
 8 
 9 func main() {
10     // 生成一个 1~100 随机数
11     rand.Seed(time.Now().UnixNano())
12     score := rand.Intn(100)
13     
14     if score >= 60 && score <= 70 {
15         fmt.Println("C")
16     } else if score > 70 && score <= 90 {
17         fmt.Println("B")
18     } else {
19         fmt.Println("A")
20     }
21 }

示例2:初始变量可以声明在布尔表达式里面,但是只在判断中生效。

 1 package main
 2 
 3 import (
 4     "fmt"
 5     "math/rand"
 6     "time"
 7 )
 8 
 9 func main() {
10     // 生成一个 1~100 随机数
11     rand.Seed(time.Now().UnixNano())
12 
13     if score := rand.Intn(100); score >= 60 && score <= 70 {
14         fmt.Println("C")
15     } else if score > 70 && score <= 90 {
16         fmt.Println("B")
17     } else {
18         fmt.Println("A")
19     }
20 
21     //fmt.Println(score)  score 作用域只在布尔表达式中
22 }

示例3:输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续判断第二个字母

 1 package main
 2 
 3 import (
 4     "fmt"
 5     "math/rand"
 6     "time"
 7 )
 8 
 9 func main() {
10     var c string
11     fmt.Println("输入一个字符:")
12     fmt.Scan(&c)
13 
14     if c == "S" {
15         fmt.Println("输入第二个字符:")
16         fmt.Scan(&c)
17         if c == "a" {
18             fmt.Println("Saturday")
19         } else if c == "u" {
20             fmt.Println("Sunday")
21         } else {
22             fmt.Println("输入错误")
23         }
24     } else if c == "F" {
25         fmt.Println("Friday")
26     } else if c == "M" {
27         fmt.Println("Monday")
28     } else if c == "T" {
29         fmt.Println("输入第二个字符:")
30         fmt.Scan(&c)
31         if c == "u" {
32             fmt.Println("Tuesday")
33         } else if c == "h" {
34             fmt.Println("Thursday")
35         } else {
36             fmt.Println("输入错误")
37         }
38     } else if c == "W" {
39         fmt.Println("Wednesday")
40     } else {
41         fmt.Println("输入错误")
42     }
43 }

2.4 if 语句嵌套使用

go语言中 if 语句也可以嵌套使用,语法如下:

1 if 布尔表达式 1 {
2    /* 在布尔表达式 1 为 true 时执行 */
3    if 布尔表达式 2 {
4       /* 在布尔表达式 2 为 true 时执行 */
5    }
6 }

示例:比较三个数的大小

 1 package main
 2 
 3 import (
 4     "fmt"
 5     "math/rand"
 6     "time"
 7 )
 8 
 9 func main() {
10     rand.Seed(time.Now().UnixNano())
11 
12     a := rand.Intn(100)
13     b := rand.Intn(100)
14     c := rand.Intn(100)
15 
16     fmt.Printf("随机生成数字a的值为:%v \n", a)
17     fmt.Printf("随机生成数字b的值为:%v \n", b)
18     fmt.Printf("随机生成数字c的值为:%v \n", c)
19 
20     if a > b {
21         if a > c {
22             fmt.Println("a最大")
23         }
24     } else {
25         if b > c {
26             fmt.Println("b最大")
27         } else {
28             fmt.Println("c最大")
29         }
30     }
31 }

3. switch 语句的使用

3.1 基本使用

switch 语句会执行满足条件的 case 分支,如果所有的 case 都未命中,则会执行 default 分支 。Go语言规定每个 switch 只能有一个 default 分支。

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func main() {
 8     finger := 3
 9     switch finger {
10     case 1:
11         fmt.Println("大拇指")
12     case 2:
13         fmt.Println("食指")
14     case 3:
15         fmt.Println("中指")
16     case 4:
17         fmt.Println("无名指")
18     case 5:
19         fmt.Println("小拇指")
20     default:
21         fmt.Println("无效的输入!")
22     }
23 }

3.2 初始变量声明

初始变量可以声明在布尔表达式里面,但是作用域只有 switch 代码段 。

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func main() {
 8     switch finger := 3; finger {
 9     case 1:
10         fmt.Println("大拇指")
11     case 2:
12         fmt.Println("食指")
13     case 3:
14         fmt.Println("中指")
15     case 4:
16         fmt.Println("无名指")
17     case 5:
18         fmt.Println("小拇指")
19     default:
20         fmt.Println("无效的输入!")
21     }
22     
23     //fmt.Println(finger) // undefined: finger
24 }

3.3 分支可以有多个值

一个分支可以有多个值,多个值中间使用英文逗号分隔。

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func main() {
 8     switch n := 7; n {
 9     case 1, 3, 5, 7, 9:
10         fmt.Println("奇数")
11     case 2, 4, 6, 8:
12         fmt.Println("偶数")
13     default:
14         fmt.Println(n)
15     }
16 }

3.4 分支的值可以是表达式

分支还可以使用表达式,这时候switch语句后面不需要再跟判断变量。

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func main() {
 8     age := 30
 9     switch {
10     case age < 25:
11         fmt.Println("好好学习吧")
12     case age > 25 && age < 35:
13         fmt.Println("好好工作吧")
14     case age > 60:
15         fmt.Println("好好享受吧")
16     default:
17         fmt.Println("活着真好")
18     }
19 }

3.5 fallthrough 的使用

fallthrough 语法可以执行满足条件的 case 的下一个 case

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func main() {
 8     s := "a"
 9     switch {
10     case s == "a":
11         fmt.Println("a")
12         fallthrough
13     case s == "b":
14         fmt.Println("b")
15         fallthrough
16     case s == "c":
17         fmt.Println("c")
18     default:
19         fmt.Println("...")
20     }
21 }

二、循环

go 语言中的所有循环类型均可以使用 for 关键字来完成。条件表达式返回true时循环体不停地进行循环,直到条件表达式返回false时自动退出循环。

1. for 语句

go语言中 for 语句的语法如下:

1 for 初始语句;条件表达式;结束语句{
2     循环体语句
3 }

示例1:基本使用,输出 1~10

1 package main
2 
3 import "fmt"
4 
5 func main() {
6     for i := 1; i <= 10; i++ {
7         fmt.Printf("i: %v \n", i)
8     }
9 }

示例2:for 循环的初始语句可以写在外面,但是初始语句后的分号必须要写

 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6     i := 1
 7     for ; i <= 10; i++ {
 8         fmt.Printf("i: %v \n", i)
 9     }
10 }

示例3:初始条件和结束条件都可以省略(结束条件可以写在循环体中)

 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6     i := 1
 7     for i <= 10 {
 8         fmt.Printf("i: %v \n", i)
 9         i ++  // 结束条件
10     }
11 }

示例4:无限循环

 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6     // 条件永远满足
 7     i := 1
 8     for i <= 10 {
 9         fmt.Printf("i: %v \n", i)
10     }
11     
12     // 或者直接写一个for关键字
13     for {
14         fmt.Println("我一直在执行~")
15     }
16 }

2. for range 语句

Go 语言中可以使用 for range 遍历数组、切片、字符串、map 及通道(channel)。 通过 for range 遍历的返回值有以下规律:

  • 数组、切片、字符串返回索引和值

  • map返回键和值。

  • 通道(channel)只返回通道内的值。

 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6     
 7     s := "hello南京"
 8     
 9     // 普通方式遍历字符串是按照单个字节遍历
10     for i := 0; i < len(s); i++ { //byte
11         fmt.Printf("%v(%c) ", s[i], s[i]) // 104(h) 101(e) 108(l) 108(l) 111(o) 229(å) 141() 151(—) 228(ä) 186(º) 172(¬) 
12     }
13     // 使用 for + range 遍历字符串,可以正常遍历出中文
14     for _, r := range s { 
15         fmt.Printf("%v(%c) ", r, r)  // 104(h) 101(e) 108(l) 108(l) 111(o) 21335(南) 20140(京) 
16     }
17 }

三、流程控制关键字

1. break 关键字

break 语句可以结束 forswitchselect 的代码块。Go 语言中使用 break 要注意以下几点:

  • 单独在 select 中使用 break 和不使用 break 没有区别。

  • switch 语句中,如果没有使用 fallthough,使用 break 和不使用 break 没有区别;如果有 fallthough,使用 break 能够终止 fallthough 后面的 case 语句的执行。

  • 带标签的 break ,可以直接跳出多层循环的作用域,不需要使用控制变量一层一层跳出循环,没有带 break 的只能跳出当前语句块。

1.1 跳出for循环

 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6 
 7     for i := 1; i <= 10; i++ {
 8         if i == 5 {
 9             break
10         }
11         
12         fmt.Println(i)  // 输出 1 2 3 4
13     }
14 }

1.2 跳出switch循环

 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6     i := 2
 7     switch i {
 8     case 1:
 9         fmt.Println("等于1")
10         break
11     case 2:
12         fmt.Println("等于2")
13         break  // 满足条件后直接退出switch。break后所有代码都不会执行
14         fallthrough
15     case 3:
16         fmt.Println("等于3")
17         break
18     default:
19         fmt.Println("不关心")
20         break
21     }
22 }

1.3 带标签的break

break 语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的 forswitchselect 的代码块上。

 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6 
 7     for i := 0; i <= 10; i++ {
 8         for j := 0; j <= 10; j++ {
 9             if j == 5 {
10                 break  // 只能退出里层的j循环,外层的i循环还是会继续执行
11             }
12 
13             fmt.Printf("j: %v\n", j)
14         }
15 
16         fmt.Printf("i: %v\n", i)
17     }
18 
19 
20 breakKey:
21     for i := 0; i <= 10; i++ {
22         for j := 0; j <= 10; j++ {
23             if j == 5 {
24                 break breakKey  // 可以退出两层循环
25             }
26 
27             fmt.Printf("j: %v\n", j)
28         }
29 
30         fmt.Printf("i: %v\n", i)
31     }
32 }

2. continue 关键字

continue 在 Go 中只能用在 for 循环中,它可以终止本次循环,直接进行下一次循环。

 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6 
 7     for i := 0; i <= 10; i++ {
 8         if i == 2 {
 9             continue  // 遇到i等于2时,直接跳过,开始下一次循环。continue后的代码不会执行
10         }
11 
12         fmt.Println(i)
13     }
14 }

continue 后也可以添加标签,表示退出标签对应的本次循环的代码块,继续开始下一次循环:

 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6 forLoop1:
 7     for i := 0; i <= 5; i++ {
 8         //forLoop2:
 9         for j := 0; j <= 5; j++ {
10             if i == 2 && j == 2 {
11                 continue forLoop1 // 当i和j都等于2时,跳过当前的j循环和i循环,直接开始循环i=3
12             }
13 
14             fmt.Printf("i: %v, j: %v\n", i, j)
15         }
16     }
17 }

3. goto 关键字

goto 语句通过标签进行代码间的无条件跳转。goto 语句可以在快速跳出循环、避免重复退出上有一定的帮助。

示例:当 j==2 时退出双层循环

 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6     // 可以通过标识位来判断是否要退出外层循环
 7     exitFlag := false
 8 
 9     for i := 0; i <= 5; i++ {
10         for j := 0; j <= 5; j++ {
11             if j == 2 {
12                 exitFlag = true
13                 break
14             }
15             fmt.Printf("i: %v, j: %v\n", i, j)
16         }
17 
18         if exitFlag {
19             break
20         }
21     }
22 }

可以使用 goto + 标签 来优化代码:

 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6 
 7     for i := 0; i <= 5; i++ {
 8         for j := 0; j <= 5; j++ {
 9             if j == 2 {
10                 goto exitFlag  // 直接跳转到标签对应的代码段处
11             }
12             fmt.Printf("i: %v, j: %v\n", i, j)
13         }
14     }
15 
16 exitFlag:
17     fmt.Println("end~")
18 }

 

 
posted @ 2023-03-27 18:44  cdcx  阅读(19)  评论(0编辑  收藏  举报