【第十二篇】一文搞懂_GO程序流程控制(下)🔥🔥

151 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情

一、Switch 分支控制:

一、基本的介绍:

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

二、基本语法:

三、switch 的流程图:

对上图的说明和总结:

  1. switch 的执行的流程,先执行表达式,得到值,然后和 case 的表达式进行比较,如果相等,就匹配到,然后执行对应的 case 的语句块,然后退出 switch 控制。
  2. 如果 Switch 的表达式的值和任何的 case 的表达式匹配成功,则执行 default 的语句块。执行后退出 switch 的控制。
  3. golang 的 case 后的表达式可以有多个,使用“逗号”间隔。
  4. golang 中的 case 语句块不需要写 break ,因为默认会有,即在默认情况下,当程序执行完 case 语句块后,就直接退出该 Switch 控制结构。

四、Switch 快速入门案例:

  1. 案例:
    1. 请编写一个程序,该程序可以接收一个字符,比如:a,b,c,d,e,f,g a表示星期一,b表示星期二..... 根据用户的输入显示相依的信息,要求使用 switch 语句完成
  1. 代码:
package main

import "fmt"

func main() {
	// 请编写一个程序,该程序可以接收一个字符,
	// 比如: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 a")
	fmt.Scanf("%c", &key)

	switch key {
	case 'a':
		fmt.Println("周一,猴子穿新衣")
	case 'b':
		fmt.Println("周二,猴子当小二")
	case 'c':
		fmt.Println("周三,猴子爬雪山")
	case 'd':
		fmt.Println("周四")
	case 'e':
		fmt.Println("周五")
	case 'f':
		fmt.Println("周六")
	case 'g':
		fmt.Println("周日")
	default:
		fmt.Println("输入有误......")
	}

}


五、Switch 的使用的注意事项和细节:

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

import "fmt"

// 写一个非常简单的函数,这里是什么意思呢,就是我传了一个b进去,返回b+1
func test(b byte) byte {
	return b + 1
}

func main() {
	// 请编写一个程序,该程序可以接收一个字符,
	// 比如: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 a")
	fmt.Scanf("%c", &key)

	// 这里只强调语法现象,是正确的
	switch test(key) + 1 {
	case 'a':
		fmt.Println("周一,猴子穿新衣")
	case 'b':
		fmt.Println("周二,猴子当小二")
	case 'c':
		fmt.Println("周三,猴子爬雪山")
	case 'd':
		fmt.Println("周四")
	case 'e':
		fmt.Println("周五")
	case 'f':
		fmt.Println("周六")
	case 'g':
		fmt.Println("周日")
	default:
		fmt.Println("输入有误......")
	}

}

  1. case 后的各个表达式的值的数据类型,必须和 switch 的表达式数据类型一致。
package main

import "fmt"

func main() {

	var n1 int32 = 20
	var n2 int32 = 20

	switch n1 {
	case n2:
		fmt.Println("ok1")
	default:
		fmt.Println("没有匹配到....")
	}
}

  1. case 后面可以带多个表达式,使用“逗号”间隔,比如 case 表达式1,表达式 2 .....

  1. case 后面的表达式如果是常量值(字面量),则要求不能重复。

  1. case 后面不需要带 break ,程序匹配到一个 case 后就会执行对应的代码块,然后退出 Switch ,如果一个都匹配不到,则执行 default
  2. default 语句不是必须的
  3. Switch 后可以不带表达式,类似 if -- else 分支来使用。【案例演示】
package main

import "fmt"

func main() {

	var age int = 10

	switch {
	case age == 10:
		fmt.Println("age == 10")

	case age == 20:
		fmt.Println("age == 20")

	default:
		fmt.Println("没有匹配到.....")
	}

	// case 中也可以对age,范围进行判断。
	var score int = 30

	switch {
	case score > 90:
		fmt.Println("成绩优秀..")

	case score >= 90 && score <= 90:
		fmt.Println("成绩优良..")

	case score >= 60 && score < 70:
		fmt.Println("成绩几个..")

	default:
		fmt.Println("不及格.....")
	}
}

  1. Switch 后也可以直接声明 / 定义一个变量 ,分号结束,不推荐 【案例演示】
package main

import "fmt"

func main() {

	// Switch 后也可以直接声明 / 定义一个变量 ,分号结束,不推荐 【案例演示】

	switch grade := 90; {
	case grade > 90:
		fmt.Println("成绩优秀..")

	case grade >= 90 && grade <= 90:
		fmt.Println("成绩优良..")

	case grade >= 60 && grade < 70:
		fmt.Println("成绩几个..")

	default:
		fmt.Println("不及格.....")
	}
}

  1. Switch 穿透 - fallthrough ,如果在 case 语句块后增加 fallthrough ,则会继续执行下一个 case ,也叫 Switch 穿透
package main

import "fmt"

func main() {

	// switch 的穿透 fallthrought

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

  1. type Switch :Switch 语句还可以被用于 type - Switch 来判断某个 interface 变量中实际指向的变量类型【还没有学 interface ,先体验一把】
package main

import (
	"fmt"
	"go/types"
)

func main() {
	var x interface{}
	var y = 10.0
	x = y
	switch i:=x.(types) {
	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 是 未知型")
}

六、Switch 的课堂练习:

  1. 使用 Switch 把小写类型的 char 型类型大写(键盘输入)。只转换 a,b,c,d,e 其它输出“other”
package main

import "fmt"

func main() {
	// 使用 Switch 把小写类型的 char 型类型大写(键盘输入)。只转换 a,b,c,d,e 其它输出“other”

	var char byte
	fmt.Println("请输入一个字符:")
	fmt.Scanf("%c", &char)

	switch char {
	case 'a':
		fmt.Println("A")
	case 'b':
		fmt.Println("B")
	case 'c':
		fmt.Println("C")
	case 'd':
		fmt.Println("D")
	case 'e':
		fmt.Println("E")
	default:
		fmt.Println("other")
	}
}

  1. 对学生成绩大于 60 分的,输出 “合格”。低于 60 分的,输出 “不合格”。(注:输入的成绩不能大于 100)
package main

import "fmt"

func main() {
	// 对学生成绩大于 60 分的,输出 “合格”。低于 60 分的,输出 “不合格”。(注:输入的成绩不能大于 100)
	var score float64
	fmt.Println("请输入成绩:")
	fmt.Scanln(&score)

	// 注:这里的取整是不严谨的,只做演示案例
	switch int(score / 60) {
	case 1:
		fmt.Println("及格")
	case 0:
		fmt.Println("不及格")
	default:
		fmt.Println("输入有误..")
	}

	// 严谨一点儿的写法
	// 比如说当你的成绩为 110 的时候,上面就会出问题。
	var grade float64
	switch {
	case grade >= 60.0 && grade <= 100.0:
		fmt.Println("及格")
	}

}

  1. 根据用户指定月份,打印该月份所属的季节。 3 4 5春季、 6 7 8 夏季 、9 10 11 秋季、 12 1 2 冬季
package main

import "fmt"

func main() {

	// 根据用户指定月份,打印该月份所属的季节。 3 4 5春季、 6 7 8 夏季 、9 10 11 秋季、 12 1 2 冬季
	var month byte
	fmt.Println("请输入月份:")
	fmt.Scanln(&month)

	switch month {
	case 3, 4, 5:
		fmt.Println("spring")
	case 6, 7, 8:
		fmt.Println("summer")
	case 9, 10, 11:
		fmt.Println("autumn")
	case 12, 1, 2:
		fmt.Println("winter")
	}
}


七、Switch 和 if 的比较:

总结了什么情况下使用 Switch,什么情况下使用 if

  1. 如果判断的具体数值不多,而且符合整数、浮点数、字符、字符串这几种类型。建议使用 Switch 语句,简洁高效。
  2. 其他情况:对区间判断和结果为 bool 类型,使用 if , if 的使用范围更广。

二、for 循环控制:

一、基本介绍:

听其名而知其意。就是让我们的一段代码循环的执行。

二、一个实际的需求:

  1. 请大家看一个案例 【for Test.go】
    1. 编写一个程序,可以打印 10 句
    2. “你好,小黄”。请大家想想怎么去做呢?
  1. 用传统的方式去实现:
  1. 用 for 循环的方式去实现

三、 for 循环的基本语法:

  1. 语法格式:
    1. for 循环变量初始化;循环条件;循环变量迭代{

循环操作(语句)

}

  1. 对上面的语法格式说明:
    1. 对 for 循环来说,有四个要素:
    2. 循环变量初始化
    3. 循环条件
    4. 循环操作(语句),有人也叫作循环体
    5. 循环变量迭代
  1. for 循环执行的顺序说明:
    1. 执行循环变量初始化,比如 i := 1
    2. 执行循环条件,比如 i <= 10
    3. 如果循环条件为真,就执行循环操作:比如 fmt.Println("......")
    4. 执行循环变量迭代,比如 i++
    5. 反复执行 2,3,4 步骤,直到 循环流程为 false ,就退出 for 循环。

四、for 循环执行流程分析

  1. for 循环的流程图:

  1. 对照代码分析 for 循环的执行过程

五、 for 循环的使用注意事项和细节讨论

  1. 循环条件是返回一个布尔值的表达式
  2. for 循环的第二种使用方式

for 循环判断 {

// 循环执行语句

}

将变量初始化和变量迭代写到其他位置

  1. 案例演示:
  1. for 循环的第三种使用方式:

for {

// 循环执行语句

}

上面的写法等价 for ;;{} 是一个无限循环,通常需要配合 break 语句使用

  1. golang 提供 for - range 的方式,可以方便遍历字符串和数组(注:数组的遍历,我们放到讲数组的时候再讲解),案例说明如何遍历字符串。

字符串遍历方式 1 - 传统方式

字符串遍历方式 2 - for - range

  1. 上面代码的细节讨论

如果我们的字符串含有中文,那么传统的遍历字符串方式,就是错误,会出现乱码。原因是传统的对字符串的变量是按照字节来遍历的,而一个汉子在 UTF-8编码是对应 3个字节

如何解决,需要要将 Str 转成 【】rune ==>

对应 for - range 遍历方式而言,是按照字符方式遍历。因此如果有字符串有中文,也是 ok 。


六、for 循环的课堂练习

  1. 打印 1- 100 之间所有是 9 的倍数的整数的个数及总和
  2. 完成下面的表达式输出,6 是可变的

三、while 和 do..while 的实现:

Go 语言没有 while 和 do .. while 语法,这一点需要同学们注意一下,如果我们需要使用类似其它语言(比如 Java / C 的 while 和 do..while ),可以通过 for 循环来实现其 使用效果。

一、while 循环的实现

说明上图:

  1. for 循环是一个无限循环
  2. break 语句就是跳出 for 循环

使用上面的 while 实现完成输出 10 句 “hello wrold”


二、do .. while 的实现

对上图的说明

  1. 上面的循环是先执行,再判断,因此至少执行一次。
  2. 当循环条件成立后,就会执行 break,break 就是跳出 for 循环,结束循环。
  3. 案例演示:

使用上面的 do ...while 实现完成输出 10 句 “hello ,ok ”