程序流程控制介绍

在程序中,程序运行的流程控制决定程序是如何执行的,是我们必须掌握的,主要有三大流程控制语句。

  1. 顺序控制
  2. 分支控制
  3. 循环控制

    顺序控制

    程序从上到下逐行地执行,中间没有任何判断和跳转,按照默认的流程执行,即顺序控制。

    顺序控制的流程图

    程序流程控制 - 图1

    顺序控制举例和注意事项

    1. 正确形式:
    2. func main() {
    3. var num1 int = 10 //声明了 num1
    4. var num2 int = num1 + 20 //使用 num1
    5. fmt.Println(num2)
    6. }
    7. 错误形式:
    8. func main() {
    9. var num2 int = num1 + 20 //使用 num1
    10. var num1 int = 10 // 声 明 num1 (×)
    11. fmt.Println(num2)
    12. }

    分支控制

    分支控制的基本介绍

    分支控制就是让程序有选择执行。有下面三种形式

  4. 单分支

  5. 双分支
  6. 多分支

    单分支控制

    基本语法

    if 条件表达式 {
     执行代码块
    }
    说明:当条件表达式为true时,就会执行{}中的代码。
    注意:{}是必须要有的,就算执行代码块只有一行代码
    

    应用案例

     //编写一个程序,可以输入人的年龄,如果该同志的年龄大于18岁,则输出 "你年龄大
     //于18,要对自己的行为负责!"
    
     //分析
     //1.年龄 ==> var age int
     //2.从控制台接收一个输入 fmt.Scanln(&age)
     //3.if判断
    
     var age int
     fmt.Println("请输入年龄:")
     fmt.Scanln(&age)
    
     if age > 18 {
         fmt.Println("你年龄大于18,要对自己的行为负责!")
     }
    

    单分支的流程图

    程序流程控制 - 图2

    单分支的细节说明

     //golang支持在if中,直接定义一个变量,比如下面
     if age := 20; age > 18 {
         fmt.Println("你年龄大于18,要对自己的行为负责!")
     }
    

    双分支控制

    基本语法

    if 条件表达式 {
     执行代码块1
    }eles {
     执行代码块2
    }
    说明:当条件表达式成立,即执行代码块1,否则执行代码块2。
    注意:{}必须要有,else不能换行
    

    应用案例

     //编写一个程序,可以输入人的年龄,如果该同志的年龄大于18岁,则输出 “你年龄大于18,要对
     //自己的行为负责!”。否则 ,输出”你的年龄不大这次放过你了.”
    
     //思路分析
     //1. 年龄 ===》 var age int
     //2. fmt.Scanln接收
     //3. if --- else
    
     //代码
     var age int
     fmt.Println("请输入年龄:")
     fmt.Scanln(&age)
    
     if age > 18 {
         fmt.Println("你年龄大于18~....")
     } else {
         fmt.Println("你的年龄不大这次放过你了")
     }
    

    双分支的流程图

    程序流程控制 - 图3

    双分支的细节说明

  7. 双分支只会执行其中的一个分支

  8. else 不能换行
  9. 条件表达式可以带()但不推荐

     if (age > 18) { //不报错 但不推荐这样写 要求写成if age > 18 { ...
         fmt.Println("你年龄大于18~....")
     }
     else { //错误 else 不能换行
         fmt.Println("你的年龄不大这次放过你了")
     }
    

    多分支控制

    基本语法

    if 条件表达式1 {
     执行代码块1
    }eles if 条件表达式2{
     执行代码块2
    }
    ...
    else {
     执行代码块n
    }
    

    多分支的判断流程如下:

  10. 先判断条件表达式 1 是否成立,如果为真,就执行代码块 1

  11. 如果条件表达式 1 为假,就去判断条件表达式 2 是否成立, 如果条件表达式 2 为真, 就执行代码块 2
  12. 依次类推
  13. 如果所有的条件表达式不成立,则执行 else 的语句块

    应用案例

    ```go //岳小鹏参加Golang考试,他和父亲岳不群达成承诺: // 如果: // 成绩为100分时,奖励一辆BMW; // 成绩为(80,99]时,奖励一台iphone7plus; // 当成绩为[60,80]时,奖励一个 iPad; // 其它时,什么奖励也没有。 // 请从键盘输入岳小鹏的期末成绩,并加以判断

    //分析思路 //1. score 分数变量 int //2. 选择多分支流程控制 //3. 成绩从键盘输入 fmt.Scanln

var score int
fmt.Println("请输入成绩:")
fmt.Scanln(&score)

//多分支判断
if score == 100 {
    fmt.Println("奖励一辆BMW")
} else if score > 80 && score <= 99 {
    fmt.Println("奖励一台iphone7plus")
} else if score >= 60 && score <= 80 {
    fmt.Println("奖励一个 iPad")
} else {
    fmt.Println("什么都不奖励")
}
<a name="zUkTF"></a>
### 多分支的流程图
![](https://cdn.nlark.com/yuque/0/2022/jpeg/2608713/1652690234172-064b0911-b91c-4a77-ab88-d7c359a9db4b.jpeg)
<a name="CjAqs"></a>
## 嵌套分支
<a name="B5lrT"></a>
### 基本介绍
在一个分支结构中又完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层分支外面的分支结构称为外层分支。
<a name="zL40f"></a>
### 基本语法
```go
if 条件表达式{
    if 条件表达式{
    }else{
    }
}
说明:嵌套分支不宜过多,建议控制在3层内

应用案例

    //参加百米运动会,如果用时8秒以内进入决赛,
    //否则提示淘汰。并且根据性别提示进入男子组或女子组。【可以让学员先练习下】, 
    //输入成绩和性别.

    //分析思路
    //1. 定义一个变量,来接收跑步使用秒数. float64
    //2. 定义一个变量,来接收性别string
    //3. 因为判断是嵌套的判断,因此我们会使用嵌套分支

    var second float64 

    fmt.Println("请输入秒数")
    fmt.Scanln(&second)

    if second <= 8 {
        //进入决赛
        var gender string
        fmt.Println("请输入性别")
        fmt.Scanln(&gender)
        if gender == "男" {
            fmt.Println("进入决赛的男子组")
        } else {
            fmt.Println("进入决赛的女子组")
        }
    } else {
        fmt.Println("out...")
    }

switch 分支控制

基本的介绍

  1. switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上到下逐一测试,直到匹配为止。
  2. 匹配项后面也不需要再加break

    基本语法

    switch 表达式{
     case 表达式1,表达式2,...:
         语句块1
     case 表达式3,表达式4,...:
         语句块2
     //这里可以有多个case语句
     default:
         语句块
    }
    

    应用案例

     //     案例:
     // 请编写一个程序,该程序可以接收一个字符,比如: a,b,c,d,e,f,g
     // a表示星期一,b表示星期二 …  根据用户的输入显示相依的信息.
    
     // 要求使用 switch 语句完成
    
     //分析思路
     //1. 定义一个变量接收字符
     //2. 使用switch完成
     var key byte
     fmt.Println("请输入一个字符 a,b,c,d,e,f,g")
     fmt.Scanf("%c", &key)
    
     switch key { //将语法现象
         case 'a':
             fmt.Println("周一, 猴子穿新衣")
         case 'b':
             fmt.Println("周二,猴子当小二")
         case 'c':
             fmt.Println("周三,猴子爬雪山")
         //...
         default:
             fmt.Println("输入有误...")
     }
    

    switch的流程图

    程序流程控制 - 图4
    对上图的说明和总结

  3. switch 的执行的流程是,先执行表达式,得到值,然后和 case 的表达式进行比较,如果相等, 就匹配到,然后执行对应的 case 的语句块,然后退出 switch 控制。

  4. 如果 switch 的表达式的值没有和任何的 case 的表达式匹配成功,则执行 default 的语句块。执行后退出 switch 的控制.
  5. golang 的 case 后的表达式可以有多个,使用 逗号 间隔.
  6. golang中的 case 语句块不需要写 break , 因为默认会有,即在默认情况下,当程序执行完 case语句块后,就直接退出该 switch 控制结构。

    switch 的细节说明

  7. case/switch 后是一个表达式( 即:常量值、变量、一个有返回值的函数等都可以)

     switch test(key)+1 { //常量值、变量、一个有返回值的函数都可以
         case 'a':
             fmt.Println("周一, 猴子穿新衣")
         case 'b':
             fmt.Println("周二,猴子当小二")
         case 'c':
             fmt.Println("周三,猴子爬雪山")
         //...
         default:
             fmt.Println("输入有误...")
     }
    
  8. case 后的各个表达式的值的数据类型,必须和 switch 的表达式数据类型一致

     var n1 int32 = 51
     var n2 int64 = 20
     switch n1 {
         case n2 :  // 错误 n2 的数据类型和n1 不一致
             fmt.Println("ok1")
         default : 
             fmt.Println("没有匹配到~")
     }
    
  9. case 后面可以带多个表达式,使用逗号间隔。比如 case 表达式 1, 表达式 2 …

     var n1 int32 = 5
     var n2 int32 = 20
     switch n1 {
         case n2, 10, 5 :  // case 后面可以有多个表达式 任意一个与n1匹配上即可执行下面的语句块
             fmt.Println("ok1")
         default : 
             fmt.Println("没有匹配到~")
     }
    
  10. case 后面的表达式如果是常量值(字面量),则要求不能重复

     var n1 int32 = 5
     var n2 int32 = 20
     switch n1 {
         case n2, 10, 5 :  
             fmt.Println("ok1")
         case 5 :  // 错误 因为前面已经有了常量5 因此重复,就会报错
             fmt.Println("ok2")
         default : 
             fmt.Println("没有匹配到~")
     }
    
  11. case 后面不需要带break , 程序匹配到一个 case 后就会执行对应的代码块,然后退出 switch,如果一个都匹配不到,则执行 default

  12. default 语句不是必须的
  13. switch 后也可以不带表达式,类似 if —else 分支来使用

     var age int = 10
    
     switch {
     case age == 10:
         fmt.Println("age == 10")
     case age == 20:
         fmt.Println("age == 20")
     default:
         fmt.Println("没有匹配到")
     }
    
  14. switch 后也可以直接声明/定义一个变量,分号结束,不推荐

     switch grade := 90; { // 在golang中,可以这样写
     case grade > 90:
         fmt.Println("成绩优秀~..")
     case grade >= 70 && grade <= 90:
         fmt.Println("成绩优良~...")
     case grade >= 60 && grade < 70:
         fmt.Println("成绩及格~...")
     default:
         fmt.Println("不及格~")
     }
    
  15. switch 穿透-fallthrough ,如果在 case 语句块后增加 fallthrough ,则会继续执行下一个 case,也叫 switch 穿透

     var num int = 10
     switch num {
     case 10:
         fmt.Println("ok1")
         fallthrough //默认只能穿透一层
     case 20:
         fmt.Println("ok2")
         fallthrough
     case 30:
         fmt.Println("ok3")
     default:
         fmt.Println("没有匹配到..")
     }
    

    输出

    ok1
    ok2
    ok3
    

    switch 和 if 的比较

  16. 如果判断的具体数值不多,而且符合整数、浮点数、字符、字符串这几种类型。建议使用 swtich语句,简洁高效。

  17. 其他情况:对区间判断和结果为 bool 类型的判断,使用 if,if 的使用范围更广

    for 循环控制

    基本介绍

    让一段代码循环的执行

    基本语法

    for 循环变量初始化;  循环条件;  循环变量迭代 {
     循环操作(语句)
    }
    

    对 for 循环来说,有四个要素:

  18. 循环变量初始化

  19. 循环条件
  20. 循环操作(语句) ,有人也叫循环体
  21. 循环变量迭代

for 循环执行的顺序说明:

  1. 执行循环变量初始化,比如i := 1
  2. 执行循环条件, 比如 i <= 10
  3. 如果循环条件为真,就执行循环操作 ,比如fmt.Println("")
  4. 执行循环变量迭代 , 比如i++
  5. 反复执行 2, 3, 4 步骤,直到 循环条件为 False ,就退出 for 循环。

    应用案例

     for i := 1; i <= 10; i++ {
         fmt.Println("hello,world", i)
     }
    

    for 循环的流程图

    程序流程控制 - 图5

    for 循环的细节说明

  6. 循环条件是返回一个布尔值的表达式

  7. for 循环的第二种使用方式,将变量初始化和变量迭代写到其它位置

     //for循环的第二种写法 
     j := 1 //循环变量初始化
     for j <= 10 { //循环条件
         fmt.Println("hello world", j)
         j++ //循环变量迭代
     }
    
  8. for 循环的第三种使用方式

     //for循环的第三种写法, 这种写法通常会配合break使用
     k := 1
     for {  // 这里也等价 for ; ; { 
         if k <= 10 {
             fmt.Println("ok~~", k)
         } else {
             break //break就是跳出这个for循环
         }
         k++
     }
    
  9. Golang 提供 for-range 的方式,可以方便遍历字符串和数组

     //字符串遍历方式1-传统方式
     var str string = "hello"
     for i := 0; i < len(str); i++ {
         fmt.Printf("%c \n", str[i]) //使用到下标...
     }
    
     //如果我们的字符串含有中文,那么传统的遍历字符串方式,就是错误,会出现乱码。
     //原因是传统的对字符串的遍历是按照字节来遍历,而一个汉字在 utf8 编码是对应 3 个字节
     //如何解决 需要要将    str 转成 []rune 切片
     // var str string = "hello 你好啊"
     // str2 := []rune(str) // 把 str 转成 []rune
     // for i := 0; i < len(str2); i++ {
     //     fmt.Printf("%c \n", str2[i]) //使用到下标...
     // }
    
     fmt.Println()
     //字符串遍历方式2-for-range
     str = "world"
     for index, val := range str {
         fmt.Printf("index=%d, val=%c \n", index, val)
     }
    

    输出 ```go h e l l o

index=0, val=w index=1, val=o index=2, val=r index=3, val=l index=4, val=d

<a name="JyuIO"></a>
# 多重循环控制
<a name="hKw56"></a>
## 基本介绍

1. 将一个循环放在另一个循环体内,就形成了嵌套循环。在外边的 for 称为外层循环在里面的 for循环称为内层循环。【**建议一般使用两层,最多不要超过 3 层**】
1. 实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为 false时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环。
1. 外层循环次数为 m 次,内层为 n 次,则内层循环体实际上需要执行 m*n 次
<a name="H37j1"></a>
## 应用案例
```go
    //1)统计3个班成绩情况,每个班有5名同学,
    //求出各个班的平均分和所有班级的平均分[学生的成绩从键盘输入]

    //分析实现思路
    //1. 统计1个班成绩情况,每个班有5名同学, 求出该班的平均分【学生的成绩从键盘输入】=》先易后难
    //2. 学生数就是5个 [先死后活]
    //3. 声明一个sum 统计班级的总分

    //分析实现思路2
    //1. 统计3个班成绩情况,每个班有5名同学, 求出每个班的平均分【学生的成绩从键盘输入】
    //2. j 表示第几个班级
    //3. 定义一个变量存放总成绩

    //分析实现思路3
    //1. 我们可以把代码做活
    //2. 定义两个变量,表示班级的个数和班级的人数

    //统计三个班及格人数,每个班有5名同学
    //分析思路
    //1. 声明以变量 passCount 用于保存及格人数

    //走代码实现
    var classNum int = 2
    var stuNum int = 5
    var totalSum float64 = 0.0
    var passCount int = 0
    for j := 1; j <= classNum; j ++ {
        sum := 0.0
        for i := 1; i <= stuNum; i++ {
            var score float64
            fmt.Printf("请输入第%d班 第%d个学生的成绩 \n", j, i)
            fmt.Scanln(&score)
            //累计总分
            sum += score
            //判断分数是否及格
            if score >= 60 {
                passCount++
            }
        }

        fmt.Printf("第%d个班级的平均分是%v\n", j, sum / float64(stuNum) )
        //将各个班的总成绩累计到totalSum
        totalSum += sum
    }

    fmt.Printf("各个班级的总成绩%v 所有班级平均分是%v\n", totalSum, totalSum / float64(stuNum * classNum))
    fmt.Printf("及格人数为%v\n", passCount)

跳转控制语句-break

基本介绍

break 语句用于终止某个语句块的执行,用于中断当前 for 循环或跳出 switch 语句

基本语法

{
    ……
    break
    ……
}

应用案例

    //100以内的数求和,求出 当和 第一次大于20的当前数
    sum := 0
    for i := 1; i <= 100; i++ {
        sum += i //求和
        if sum > 20 {
            fmt.Println("当sum>20时,当前数是", i)
            break
        }
    }

break 的细节说明

  1. break 语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块

    lable1:
     for i := 0; i < 4; i++ {
         // lable2: //设置一个标签
         for j := 0; j < 10; j++ {
             if j == 2 {
                 // break //break 默认会跳出最近的for循环
                 break lable1 //跳到 lable1:处
                 // break lable2
             }
             fmt.Println("j=", j)
         }
     }
    
  2. break 默认会跳出最近的 for 循环

  3. break 后面可以指定标签,跳出标签对应的 for 循环

    跳转控制语句-continue

    基本介绍

    continue 语句用于结束本次循环,继续执行下一次循环
    continue 语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环 , 这个和前面的 break 标签的使用的规则一样.

    基本语法

    {    
     ……
     continue
     ……
    }
    

    应用案例

     for i := 0; i < 4; i++ {
         for j := 0; j < 10; j++ {
             if j == 2 {
                 continue
             }
             fmt.Println("j=", j)
         }
     }
    
     //这里演示一下指定标签的形式来使用
     here:
         for i := 0; i < 2; i++ {
             for j := 1; j < 4; j++ {
                 if j == 2 {
                     continue here
                 }
                 fmt.Println("i=", i, "j=", j)
             }
         }
    

    跳转控制语句-goto

    基本介绍

  4. Go 语言的 goto 语句可以无条件地转移到程序中指定的行。

  5. goto 语句通常与条件语句配合使用。可用来实现条件转移,跳出循环体等功能。
  6. 在 Go 程序设计中一般不主张使用 goto 语句, 以免造成程序流程的混乱,使理解和调试程序都产生困难

    基本语法

    goto label
    .. .
    label: statement
    

    应用案例

     var n int = 30
     // 演示goto的使用
     fmt.Println("ok1")
     if n > 20 {
         goto label1
     }
     fmt.Println("ok2")
     fmt.Println("ok3")
     fmt.Println("ok4")
     label1:
     fmt.Println("ok5")
     fmt.Println("ok6")
     fmt.Println("ok7")
    

    输出

    ok1
    ok5
    ok6
    ok7
    

    跳转控制语句-return

    基本介绍

    return 使用在方法或者函数中,表示跳出所在的方法或函数

    应用案例

     var n int = 30
     //演示return的使用
     fmt.Println("ok1")
     if n > 20 {
         return
     }
     fmt.Println("ok2")
     fmt.Println("ok3")
     fmt.Println("ok4")
     fmt.Println("ok5")
     fmt.Println("ok6")
     fmt.Println("ok7")
    

    输出

    ok1
    

    return的使用细节

  7. 如果 return 是在普通的函数,则表示跳出该函数,即不再执行函数中 return 后面代码,也可以理解成终止函数

  8. 如果 return 是在 main 函数,表示终止 main 函数,也就是说终止程序。