Go语言の程序流程控制
程序流程控制介绍
在程序中,程序运行的流程控制决定程序是如何执行的,是我们必须掌握的,主要有三大流程控制语句。
- 顺序控制
- 分支控制
- 循环控制
顺序控制
程序从上到下逐行执行,中间没有任何判断和跳转。
一个案例说明,必须下面的代码中,没有判断,也没有跳转,因此程序按照默认的流程执行,即顺序控制。
package main
import (
"fmt"
)
func main(){
var days int = 97
var week int = days / 7
var day int = days % 7
fmt.Printf("%d个星期零%d天\n", week, day)
var huashi float32 = 134.2
var sheshi float32 = 5.0 / 9 * (huashi - 100)
fmt.Printf("%v 对应的摄氏温度=%v \n", huashi, sheshi)
}
13个星期零6天
134.2对应的摄氏温度= 19
程序控制的流程图
顺序控制举例和注意事项
Golang中定义变量时采用合法的前向引用。如:
func main(){
var num1 int = 10 //声明了num1
var num2 int = num1 + 20 //使用num1
fmt.Println(num2)
}
错误形式:
func main(){
var num2 int = num1 + 20 //使用num1
var num1 int = 10 //声明num1 (❌)
fmt.Println(num2)
}
分支控制
分支控制的基本介绍
分支控制就是让程序有选择执行。有下面三种形式
- 单分支
- 双分支
- 多分枝
单分支控制
- 基本语法
if 条件表达式{
执行代码块
}
说明:当条件表达式为true时,就会执行{}的代码。注意{}是必须有的,就算你只写一行代码。
- 应用案例
编写一个程序,可以输入人的年龄,如果该同志的年龄大于 18 岁,则输出 “你年龄大 于 18,要对自己的行为负责!”。 需求—【分析】—>代码
func main() {
var age int
fmt.Println("请输入年龄:")
fmt.Scanln(&age)
if age > 18 {
fmt.Println("你年龄大于18,要对自己的行为负责!")
}
}
➜ main go run ./main.go
请输入年龄:
10
➜ main go run ./main.go
请输入年龄:
29
你年龄大于18,要对自己的行为负责!
➜ main
单分支的流程图
流程图可以用图形方式来更加清晰的描述程序执行的流程。
单分支的细节说明
if age := 20; age > 18{
fmt.Println("你年龄大于18,要对自己的行为负责!")
}
双分支控制
- 基本语法
if 条件表达式{
执行代码块1
} else {
执行代码块2
}
说明:当条件表达式成立,即执行代码块1,否则执行代码块2.{}也是必须有的。
- 应用案例
编写一个程序,可以输入人的年龄,如果该同志的年龄大于 18 岁,则输出 “你年龄大于 18,要对 自己的行为负责!”。否则 ,输出”你的年龄不大这次放过你了.”
package main
import (
"fmt"
)
func main() {
var age int
fmt.Println("请输入年龄:")
fmt.Scanln(&age)
if age > 18 {
fmt.Println("你年龄大于18,要对自己的行为负责!")
} else {
fmt.Println("你的年龄不大这次放过你了.")
}
}
➜ main go run ./main.go
请输入年龄:
19
你年龄大于18,要对自己的行为负责!
➜ main go run ./main.go
请输入年龄:
12
你的年龄不大这次放过你了.
- 双分支流程图的分析
- 对双分支的总结
- 从上图看,条件表达式就是age>18
- 执行代码块1 就是 fmt.Prinltn(“你的年龄大于18”)…
- 执行代码块2 就是 fmt.Println(“你的年龄不大”)…
- 双分支只会执行其中的一个分支。
单分支和双分支的案例
- 对下列代码,若有输出,指出输出结果.
var x int = 4
var y int = 1
if (x > 2){
if(y > 2){
fmt.Println(x + y))
}
fmt.Println("hihihi")
}else{
fmt.Println("x is =",x)
}
//输出结果是 hihihi
- 对下列代码,若有输出,指出输出结果.
var x int = 4
if x > 2
fmt.Println("ok")
else
fmt.Println("hello")
//没有{} 所以编译错误哦
- 对下列代码,若有输出,指出输出结果.
var x int = 4
if x > 2{
fmt.Println("ok")
}
else {
fmt.Println("hello")
}
//编译错误,因为else不能换行
- 对下列代码,若有输出,指出输出结果.
var x int = 4
if (x > 2){
fmt.Println("ok")
}
else {
fmt.Println("hello")
}
//输出ok 但是建议把if(x>2)写成if x > 2
- 编写程序,声明 2 个 int32 型变量并赋值。判断两数之和,如果大于等于 50,打印“hello world!
func main(){
var n1 int32 = 10
var n2 int32 = 50
if n1 + n2 >=50 {
fmt.Println("hello,world")
}
}
- 编写程序,声明 2 个 float64 型变量并赋值。判断第一个数大于 10.0,且第 2 个数小于 20.0,打 印两数之和。
var n3 float64 = 11.0
var n4 float64 = 17.0
if n3 > 10.0 && n4 < 20.0 {
fmt.Println("和=",(n3+n4))
}
- 定义两个变量 int32,判断二者的和,是否能被 3 又能被 5 整除,打印提示信息
var num1 int32 = 10
var num2 int32 = 5
if (num1 + num2) % 3 == 0 && (num1 + num2) % 5 == 0{
fmt.Println("能被3又能被5整除")
}
- 判断一个年份是否是闰年,闰年的条件是符合下面二者之一:(1)年份能被4整除,但不能被100 整除;(2)能被 400 整除
var year int = 2019
if (year % 4 == 0 && year % 100 != 0)|| year % 400 == 0{
fmt.Println(year, "是闰年!``")
}
多分支控制
- 基本语法
if 条件表达式1 {
执行代码块1
}else if{
执行代码块2
}
...
else {
执行代码块n
}
- 说明:
- 多分支的判断流程如下:
- 先判断条件表达式1是否成立,如果为真,就执行代码块1
- 如果条件表达式1如果为假,就去判断条件表达式2是否成立,如果条件表达式2为真,就执行代码块2
- 以此类推
- 如果所有的条件表达式不成立,则执行else的语句块。
- else 不是必须的
- 多分支只能有一个执行入口。
- 看一个多分支的流程图
- 多分支的快速入门案例
岳小鹏参加 Golang 考试,他和父亲岳不群达成承诺: 如果:
成绩为 100 分时,奖励一辆 BMW;
成绩为(80,99]时,奖励一台 iphone7plus;
当成绩为[60,80]时,奖励一个 iPad;
其它时,什么奖励也没有。 请从键盘输入岳小鹏的期末成绩,并加以判断
func main(){
var score int
fmt.Print("请输入成绩:")
fmt.Scanln(&score)
if score == 100{
fmt.Println("奖励BMW")
}else if score > 80 && score <= 99 {
fmt.Println("奖励一台iphone12 pro max")
}else if score >= 60 && score <=80 {
fmt.Println("奖励一个iPad")
}else {
fmt.Println("啥也没")
}
}
多分支的课堂练习
案例演示2
func main(){
var b bool = true
if b == false {
fmt.Println("a")
} else if b{
fmt.Println("b")
} else if !b{
fmt.Println("c")//c
}else {
fmt.Println("d")
}
}
//输出结果是b
//如果写成b=flase;能编译通过吗?如果能,结果是?(不能通过,if的条件表达式不是赋值语句)
案例演示3
package main
import (
"fmt"
"math"
)
func main() {
var a float64 = 1.0
var b float64 = 4.0
var c float64 = 2.0
m := b * b - 4 * a * c
//多分支判断
if m > 0 {
x1 := (-b + math.Sqrt(m)) / 2 * a
x2 := (-b - math.Sqrt(m)) / 2 * a
fmt.Printf("x1=%v x2=%v \n", x1, x2)
}else if m == 0{
x1 := (-b + math.Sqrt(m)) / 2 * a
fmt.Printf("x1=%v\n", x1)
}else {
fmt.Println("无解...")
}
}
➜ main go run ./main.go
x1=-4%
➜ main go run ./main.go
x1=-0.5857864376269049 x2=-3.414213562373095%
➜ main go run ./main.go
x1=-0.5857864376269049 x2=-3.414213562373095
➜ main
案例演示4
var height int32
var money float32
var handsome bool
fmt.Println("请输入身高(厘米)")
fmt.Scanln(&height)
fmt.Println("请输入财富(千万)")
fmt.Scanln(&money)
fmt.Println("请输入是否帅气(true or false)")
fmt.Scanln(&handsome)
if height > 180 && money >1.0 && handsome {
fmt.Println("一定要嫁给他!!!")
} else if height > 180 || money >1.0 || handsome{
fmt.Println("勉勉强强嫁给他吧")
}else {
fmt.Println("不嫁......")
}
➜ main go run ./main.go
请输入年龄:
10
➜ main go run ./main.go
请输入年龄:
29
➜ main go run ./main.go
请输入身高(厘米)
190
请输入财富(千万)
12
请输入是否帅气(true or false)
true
一定要嫁给他!!!
➜ main go run ./main.go
请输入身高(厘米)
120
请输入财富(千万)
1
请输入是否帅气(true or false)
false
不嫁......
➜ main go run ./main.go
请输入身高(厘米)
120
请输入财富(千万)
1.2
请输入是否帅气(true or false)
false
勉勉强强嫁给他吧
➜ main
嵌套分支
基本介绍
在一个分支结构中又完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层分支外面的分支结构称为外层分支。
基本语法
if 条件表达式{
if 条件表达式{
}else {
}
}
说明:嵌套分支不宜过多,建议控制在3层内
- 示例代码1
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......")
}
➜ main go run ./main.go
请输入秒数
100
out......
➜ main go run ./main.go
请输入秒数
3
请输入性别
男
进入决赛的男子组
➜ main go run ./main.go
请输入秒数
4
请输入性别
女
进入决赛的女子组
示例代码2
出票系统:根据淡旺季的月份和年龄,打印票价
4到10是旺季:
成人(18-60):60
儿童(<18):半价 30
老人(>60): 1/3 20
淡季:
成人:40
其他:20
var month int
var age int
fmt.Println("请输入月份")
fmt.Scanln(&month)
if(month>=4 && month <=10){
fmt.Println("请输入购票人年龄:")
fmt.Scanln(&age)
if age<18 {
fmt.Println("您购买的票是旺季儿童票,享受半价优惠:30元")
}else if age > 60{
fmt.Println("您购买的票是旺季老人票,享受1/3折:20元")
}else {
fmt.Println("您购买的票是旺季成人票,原价购买,60元")
}
}else {
fmt.Println("请输入购票人年龄:")
fmt.Scanln(&age)
if age<18 || age>60 {
fmt.Println("您购买的票是淡季其他票,享受半价优惠:20元")
}else {
fmt.Println("您购买的票是淡季成人票,原价购买,40元")
}
}
➜ main go run ./main.go
请输入秒数
100
➜ main go run ./main.go
# command-line-arguments
➜ main go run ./main.go
请输入月份
6
请输入购票人年龄:
19
您购买的票是旺季成人票,60元
➜ main go run ./main.go
请输入月份
2
请输入购票人年龄:
12
您购买的票是淡季其他票,20元
➜ main go run ./main.go
请输入月份
9
请输入购票人年龄:
61
您购买的票是旺季老人票,20元
➜ main go run ./main.go
请输入月份
10
请输入购票人年龄:
71
您购买的票是旺季老人票,20元
➜ main
switch分支控制
基本介绍
- switch语句用于基于不同条件执行不同动作,每一个case分支都是唯一的,从上到下逐疫测试,知道匹配为止。
- 匹配项后面也不需要再加break
基本语法
switch 表达式 {
case 表达式1,表达式2,...:
语句块1
case 表达式3,表达式4,...:
语句块2
//这里可以有多个case语句
default:
语句块
}
switch的流程图
- 说明和总结
- switch的执行的流程是,先执行表达式,得到值,然后和case的表达式进行比较,如果相等,就匹配到,然后执行对应的case的语句块,然后退出switch控制。
- 如果switch的表达式的值没有和任何的case的表达式匹配成功,则执行default的语句块,执行后退出switch的控制
- golang的case后的表达式可以有多个,使用 逗号 间隔。
- golang中的case语句块不需要写break,因为默认会有,即在默认情况下,当程序执行完case语句块后,就直接退出该switch控制结构。
switch快速入门案例
案例:
请编写一个程序,该程序可以接收一个字符,比如: a,b,c,d,e,f,g a表示星期一,b表示星期二 … 根据用户的输入显示相依的信息.要求使用 switch 语句完成
代码
package main
import (
"fmt"
)
func main() {
//分析思路
//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("周三")
case 'd':
fmt.Println("周四")
case 'e':
fmt.Println("周五")
case 'f':
fmt.Println("周六")
case 'g':
fmt.Println("周日")
default:
fmt.Println("输入有误...")
}
}
请输入一个字符 a,b,c,d,e,f,g
a
周一
➜ main
➜ main go run ./main.go
请输入一个字符 a,b,c,d,e,f,g
q
输入有误...
switch的使用的注意事项
- case/switch后是一个表达式(即:常量值、变量、一个有返回值的函数等都可以)
//写一个很简单的函数
func test(char byte) byte {
return char + 1
}
func main(){
//
var key byte
fmt.Println("请输入一个字符 a,b,c,d,e,f,g")
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("输入有误...")
}
}
- case后的各个表达式的值的数据类型,必须和switch的表达式数据类型一致
func main() {
var n1 int32 = 20
var n2 int64 = 20
switch n1 {
case n2 :
fmt.Println("ok1") //错误,因为n2和n1的数据类型不一致
default :
fmt.Println("没匹配到")
}
}
- case 后面可以带多个表达式,使用逗号间隔。比如
case 表达式1,表达式2...
func main() {
var n1 int32 = 20
var n2 int32 = 20
switch n1 {
case n2, 10, 5 :
fmt.Println("ok1")
default :
fmt.Println("没匹配到")
}
}
- case后面的表达式如果是常量值(字面量),则要求不能重复
func main() {
var n1 int32 = 5
var n2 int32 = 20
switch n1 {
case n2, 10, 5 : //case后面可以有多个表达式
fmt.Println("ok1")
case 5 : // 错误,因为前面我们有常量5,因此重复,就会报错哦
fmt.Println("ok2~")
default :
fmt.Println("没匹配到")
}
}
- case后面不需要带break,程序匹配到一个case后就会执行对应的代码块,然后退出switch,如果一个都匹配不到,则执行default
- default语句不是必须的
- 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("没有匹配到哦")
}
score := 90
switch {
case score > 90 :
fmt.Println("成绩优秀..")
case score >=70 && score <= 90:
fmt.Println("成绩优良..")
case score >=60 && score <= 70:
fmt.Println("成绩及格..")
default:
fmt.Println("不及格!")
}
}
- switch后也可以直接声明/定义一个变量,分号结束,不推荐。
switch grade := 90; {
case grade > 90 :
fmt.Println("成绩优秀..")
case grade >=70 && grade <= 90:
fmt.Println("成绩优良..")
case grade >=60 && grade <= 70:
fmt.Println("成绩及格..")
default:
fmt.Println("不及格!")
}
- switch穿透-fallthrough,如果在case语句块后增加fallthrough,则会继续执行下一个case,也叫switch穿透。
//switch的穿透fallthrought
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("没有匹配到哦")
}
➜ main go run ./main.go
ok1
ok2
ok3
➜ main
- Type Switch : switch 语句还可以被用于 type-switch 来判断某个interface变量中实际指向的变量类型【interface体验】
var x interface{}
var y = 10.0
x = y
switch i := x.(type) {
case nil:
fmt.Printf(" x 的类型~ : %T",i)
fmt.Println()
case int:
fmt.Printf("x 是 int 型")
fmt.Println()
case float64:
fmt.Printf("x 是 float64 型 ")
fmt.Println()
case func(int) float64:
fmt.Printf("x 是 func(int) 型")
fmt.Println()
case bool, string:
fmt.Printf("x 是 bool 或 string 型")
fmt.Println()
default:
fmt.Printf("未知型")
fmt.Println()
}
➜ main go run ./main.go
x 是 float64 型
switch课堂练习
- 使用switch把小写类型的char型转为大写(键盘输入)。只转换a,b,c,d,e 其他的输出”other”。
func main() {
var ch byte
fmt.Scanf("%c",&ch) //获取输入
//fmt.Printf("%c",ch)
//fmt.Println();
switch ch {
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")
}
}
- 对学生成绩大于60分的,输出“合格”。低于60分的,输出“不合格”。(注:输入的成绩不能大于100)
func main() {
var score float64
fmt.Println("请输入成绩")
fmt.Scanln(&score)
switch int(score / 60) {
case 1:
fmt.Println("及格")
case 0:
fmt.Println("不及格")
default:
fmt.Println("输入有误...")
}
}
➜ main go run ./main.go
请输入成绩
86
及格
➜ main go run ./main.go
请输入成绩
12
不及格
switch和if的比较
总结了什么情况下使用switch,什么情况下使用if
- 如果判断的具体数值不多,而且符合整数、浮点数、字符、字符串这几种类型。建议使用switch语句,简洁高效。
- 其他情况:对区间判断和结果为bool类型的判断,使用if,if的使用范围更广。
for循环控制
基本介绍
听其名而知其意。这就是让我们的一段代码循环的执行。
一个实际的需求
案例:
编写一个程序,可以打印10句
“你好 Golang!”。想一想怎么做?
- 使用传统的方式实现
func main(){ fmt.Println("你好 Golang") fmt.Println("你好 Golang") fmt.Println("你好 Golang") fmt.Println("你好 Golang") fmt.Println("你好 Golang") fmt.Println("你好 Golang") fmt.Println("你好 Golang") fmt.Println("你好 Golang") fmt.Println("你好 Golang") fmt.Println("你好 Golang") }
- for循环的快速入门
for i := 1; i <= 10; i++ { fmt.Println("你好 Golang") }
for循环的基本语法
语法格式
for 循环变量初始化;循环条件;循环变量迭代 { 循环操作(语句) }
对上面的语法格式说明
- 对for循环来说,有四个要素:
- 循环变量初始化
- 循环条件
- 循环操作(语句),有人也叫循环体
- 循环变量迭代
- 对for循环来说,有四个要素:
for循环执行的顺序说明:
- 执行循环变量初始化,比如
i:=1
- 执行循环条件,比如
i <= 10
- 如果循环条件为真,就执行循环操作:比如
fmt.Println("...")
- 执行循环变量迭代,比如
i++
- 反复执行2, 3, 4步骤,直到 循环条件为False,就退出for循环。
- 执行循环变量初始化,比如
for循环执行流程分析
- for循环的流程图
- 对照代码分析for循环的执行过程
for循环的使用注意事项和细节讨论
- 循环条件是返回一个布尔值的表达式
- for循环的第二种使用方式
for 循环执行条件 {
//循环执行语句
}
将变量初始化和变量迭代写到其他位置
- 案例演示:
- for循环的第三种使用方式
for {
//循环执行语句
}
上面的写法等价 for ; ; {}
是一个无限循环,通常需要配合break语句使用
- Golang提供for-range的方式,可以方便遍历字符串和数组(注:数组的遍历,我们放到讲数组的时候再讲解),案例说明如何遍历字符串。
- 字符串遍历方式1-传统方式
var str string = "hello,world"
for i := 0; i < len(str); i++ {
fmt.Printf("%c \n", str[i])//使用到下标
}
- 字符串遍历方式2-for-range
fmt.Println()
str = "abc~ok"
for index, val := range str {
fmt.Printf("index=%d, val=%c \n",index, val)
}
上面代码的细节讨论
如果我们的字符串含有中文,那么传统的遍历字符串方式就是错误的,会出现乱码。原因是传统的对字符串的遍历是按照字节来遍历,而一个汉字在utf8编码是对应3个字节。
如何解决?
需要要将 str 转成 []rune切片。
var str string = "hello,world!北京"
str2 := []rune(str) // 就是把str转成[]rune
for i :=0; i < len(str2); i++ {
fmt.Printf("%c \n", str2[i])//使用到下标
}
对应for-range遍历方式而言,是按照字符方式遍历。因此如果有字符串有中文,也是ok的
var str string = "abc~ok上海"
for index, val := range str {
fmt.Printf("index=%d, val=%c \n", index, val)
}
golang中还有一个byte数据类型与rune相似,它们都是用来表示字符类型的变量类型。它们的不同在于:
- byte 等同于int8,常用来处理ascii字符
- rune 等同于int32,常用来处理unicode或utf-8字符
for循环的课堂练习
- 打印1-100之间所有是9的倍数的整数的个数及总和。
package main
import (
"fmt"
)
func main() {
var sum int = 0
for i := 0; i <= 100; i++ {
if i%9==0 {
fmt.Printf("%d ",i)
sum += i
}
}
fmt.Println()
fmt.Printf("sum = %d \n",sum)
}
➜ main go run ./main.go
0 9 18 27 36 45 54 63 72 81 90 99
sum = 594
➜ main
- 完成下面的表达式输出,6是可变的。
package main
import (
"fmt"
)
func main() {
var n int
fmt.Printf("请输入参数:")
fmt.Scanln(&n)
var m int = n
for i := 0; i <= n; i++ {
fmt.Printf("%d + %d = %d \n",i,m,(i+m))
m--;
}
}
➜ main go run ./main.go
请输入参数:6
0 + 6 = 6
1 + 5 = 6
2 + 4 = 6
3 + 3 = 6
4 + 2 = 6
5 + 1 = 6
6 + 0 = 6
➜ main go run ./main.go
请输入参数:8
0 + 8 = 8
1 + 7 = 8
2 + 6 = 8
3 + 5 = 8
4 + 4 = 8
5 + 3 = 8
6 + 2 = 8
7 + 1 = 8
8 + 0 = 8
while和do..while的实现
Go语言没有while和do…while语法,这一点需要注意,如果我们需要使用类似的其他语言(java/c的while和do…while),可以通过for循环来实现其使用效果。
while循环的实现
循环变量初始化
for {
if 循环条件表达式 {
break //跳出for循环..
}
循环操作(语句)
循环变量迭代
}
- 说明
- for循环是一个无限循环
- break语句就是跳出for循环
- 使用上面的while实现完成输出10句“HelloWorld”
i := 10
for {
if i==0 {
break;
}
fmt.Printf("HelloWorld \n")
i--
}
do..while的实现
循环变量初始化
for {
循环操作(语句)
循环变量迭代
if 循环条件表达式 {
break //跳出for循环..
}
}
说明
- 上面的循环是先执行,再判断,因此至少执行一次。
- 当循环条件成立后,就会执行break,break就是跳出for循环,结束循环。
案例演示
使用do..while实现10句“HelloWorldd”
i := 10
for {
fmt.Printf("HelloWorld \n")
i--
if i==0 {
break;
}
}
多重循环控制(重点,难点)
基本介绍
- 将一个循环放在另一个循环体内,就形成了嵌套循环。在外边的 for 称为外层循环在里面的 for 循环称为内层循环。【建议一般使用两层,最多不要超过3层】
- 实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为 false 时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环。
- 外层循环次数为 m 次,内层为 n 次,则内层循环体实际上需要执行 m*n 次
应用案例
- 统计 3 个班成绩情况,每个班有 5 名同学,求出各个班的平均分和所有班级的平均分[学生的成绩从键盘输入]
func main() {
var classNum int = 3
var stuNum int = 5
var sum float64 = 0.0
var score float64 = 0.0
var totalsum float64 = 0.0
for i := 1; i <= classNum; i++ {
sum = 0.0
for j := 1; j <= stuNum; j++ {
fmt.Printf("请输入%d班级的 第%d个学生的成绩: \n", i, j)
fmt.Scanln(&score)
sum += score
}
fmt.Printf("第%d个班级的平均分为:%v \n", i, sum / (float64)(stuNum))
totalsum += sum
}
fmt.Printf("全体学生的平均分为: %v \n", totalsum / (float64)((classNum) * stuNum))
}
- 统计三个班及格人数,每个班有5名同学
func main() {
var classNum int = 3
var stuNum int = 5
var sum float64 = 0.0
var score float64 = 0.0
var totalsum float64 = 0.0
for i := 1; i <= classNum; i++ {
sum = 0.0
topNum := 0
for j := 1; j <= stuNum; j++ {
fmt.Printf("请输入%d班级的 第%d个学生的成绩: \n", i, j)
fmt.Scanln(&score)
if score >= 60 {
topNum++
}
sum += score
}
fmt.Printf("第%d个班级的及格人数为%d, 平均分为:%v \n", i, topNum, sum / (float64)(stuNum))
totalsum += sum
}
fmt.Printf("全体学生的平均分为: %v \n", totalsum / (float64)((classNum) * stuNum))
}
➜ main go run ./main.go
请输入1班级的 第1个学生的成绩:
88
请输入1班级的 第2个学生的成绩:
88
请输入1班级的 第3个学生的成绩:
66
请输入1班级的 第4个学生的成绩:
77
请输入1班级的 第5个学生的成绩:
88
第1个班级的平均分为:81.4
请输入2班级的 第1个学生的成绩:
请输入2班级的 第2个学生的成绩:
9
请输入2班级的 第3个学生的成绩:
00
请输入2班级的 第4个学生的成绩:
7
请输入2班级的 第5个学生的成绩:
6
➜ main go run ./main.go
请输入1班级的 第1个学生的成绩:
59
请输入1班级的 第2个学生的成绩:
59
请输入1班级的 第3个学生的成绩:
5
请输入1班级的 第4个学生的成绩:
69
请输入1班级的 第5个学生的成绩:
69
第1个班级的及格人数为2, 平均分为:52.2
请输入2班级的 第1个学生的成绩:
99
请输入2班级的 第2个学生的成绩:
99
请输入2班级的 第3个学生的成绩:
99
请输入2班级的 第4个学生的成绩:
99
请输入2班级的 第5个学生的成绩:
99
第2个班级的及格人数为5, 平均分为:99
请输入3班级的 第1个学生的成绩:
98
请输入3班级的 第2个学生的成绩:
98
请输入3班级的 第3个学生的成绩:
98
请输入3班级的 第4个学生的成绩:
98
请输入3班级的 第5个学生的成绩:
98
第3个班级的及格人数为5, 平均分为:98
全体学生的平均分为: 83.06666666666666
- 打印金字塔 【经典案例】
使用for循环完成下面的案例:请编写一个程序,可以接受一个整数,表示层数,打印出金字塔。
func main() {
/*
*
***
*****
*******
*********
*/
var n int
fmt.Printf("请输入层数:")
fmt.Scanln(&n)
for i := 1; i <= n; i++ {
for j := i; j <= n; j++ {
fmt.Printf(" ")
}
for k := 0; k < 2 * i - 1 ; k++ {
fmt.Printf("*")
}
fmt.Println()
}
有手就行
请输入层数:3
*
***
*****
➜ main go run ./main.go
请输入层数:5
*
***
*****
*******
*********
➜ main go run ./main.go
请输入层数:12
*
***
*****
*******
*********
***********
*************
***************
*****************
*******************
*********************
***********************
➜ main
- 打印出九九乘法表
func main() {
for i := 1; i <= 9; i++ {
for j := 1; j <= i; j++ {
fmt.Printf("%d*%d=%d\t", j, i, i * j)
}
fmt.Println()
}
}
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
跳转控制语句–break
看一个具体需求,引出break
随机生成1-100的一个数,直到生成了99这个数,看看你一共用了几次?
分析:
编写一个无限循环的控制,不停的生成随机数,当生成了99时,退出这个无限循环
//如何生成随机数
//在Go中需要生成一个随机种子,否则返回的值总是固定的。
//time.Now().Unix():返回一个从1970.1.1 00:00:00到现在的秒数
rand.Seed(time.Now().Unix())
fmt.Println("n",rand.Intn(100)+1)
break的快速入门案例
func main() {
var n int = 0
var count int = 0
rand.Seed(time.Now().Unix())
for ;; {
n = rand.Intn(100)+1
if n==99{
break
}else {
count++
}
}
fmt.Printf("生成99共进行了 %d 次",count)
fmt.Println()
}
- 运行结果:
➜ main go run ./main.go
生成99共进行了 26 次
➜ main go run ./main.go
生成99共进行了 76 次
➜ main go run ./main.go
生成99共进行了 15 次
➜ main go run ./main.go
生成99共进行了 15 次
➜ main go run ./main.go
生成99共进行了 25 次
基本介绍
break语句用于终止某个语句块的执行,用于中断当前for循环或跳出switch语句。
基本语法
{
..........
..........
break
..........
..........
}
以for循环使用break为例,画出示意图
break的注意事项和使用细节
- break语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块
- 案例:
func main() {
var i int
var j int
var k int
//lable2:
for i = 0; i < 4; i++ {
lable1:
for j = 0; j < 10; j++ {
for k = 0; k < 122; k++ {
if k == 2 {
//break // break 默认会跳出最近的for循环
break lable1
//break lable2
}
}
}
}
fmt.Printf("i:%d j:%d k:%d \n", i, j, k)
}
- 对上面案例的说明:
- break默认会跳出最近的for循环
- break后面可以指定标签,跳出标签对应的for循环
课堂练习
- 100以内的数求和,求出 当和 第一次大于20的当前数
func main() {
var sum int = 0
var i int = 0
for i = 0; i < 100; i++ {
sum += i
if(sum>20){
break
}
}
fmt.Printf("i:%d \n", i)
}
➜ main go run ./main.go
i:6
➜ main
- 实现登录验证,有三次机会,如果用户名为“张无忌”,密码“888”提示登录成功,否则提示还有几次机会。
func main() {
var username string = "张无忌"
var loginname string = ""
var loginpwd string = ""
var pwd string = "888"
var count int = 3
for ;; {
if count > 0 {
fmt.Printf("欢迎登陆,剩余的尝试登录次数错误次数:%d次 \n", count)
fmt.Printf("请输入用户名:")
fmt.Scanf("%s",&loginname)
fmt.Printf("请输入密码:")
fmt.Scanf("%s",&loginpwd)
}else{
fmt.Println("已经无法继续登陆了!")
}
if loginname == username && loginpwd == pwd {
fmt.Println("登录成功!")
break
}else {
count--
fmt.Printf("密码输入错误,剩余尝试次数减一!\n")
}
}
}
➜ main go run ./main.go
欢迎登陆,剩余的尝试登录次数错误次数:3次
请输入用户名:张三丰
请输入密码:888
密码输入错误,剩余尝试次数减一!
欢迎登陆,剩余的尝试登录次数错误次数:2次
请输入用户名:张无忌
请输入密码:888
登录成功!
跳转控制语句-continue
基本介绍
- continue语句用于结束本次循环,继续执行下一次循环。
- continue语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环,这个和前面的break标签的使用的规则一样。
基本语法
{
......
continue
......
}
continue流程图
案例分析continue的使用
continue的课堂练习
- continue实现:打印1到100之间的奇数(要求使用for循环+continue)
func main() {
for i := 0; i < 100; i++ {
if i%2 == 0 {
continue
}else {
fmt.Printf("%d ",i)
}
}
fmt.Println()
}
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99
跳转控制语句-goto
goto的基本介绍
- Go语言的goto语句可以无条件地转移到程序中指定的行。
- goto语句通常与条件语句配合使用。可用来实现条件转移,跳出循环体等功能。
- 在Go程序设计中一般不主张使用goto语句,以免造成程序流程的混乱,使理解和调试程序都产生困难
goto基本语法
goto label
......
label:statement
goto的流程图
快速入门案例
func main() {
var n int = 30
//演示goto的使用
fmt.Println("ok1")
if n > 20 {
goto label1
}
fmt.Println("ok2")
fmt.Println("ok3")
label1:
fmt.Println("ok4")
fmt.Println("ok5")
fmt.Println("ok6")
fmt.Println("ok7")
}
➜ main go run ./main.go
ok1
ok4
ok5
ok6
ok7
跳转控制语句-return
介绍
return使用在方法或者函数中,表示跳出所在的方法或函数,在讲解函数的时候,会详细的介绍。
func main(){
for i := 1; i <= 10; i++ {
if i==3 {
return
}
fmt.Println("哇哇",i)
}
fmt.Println("Hello World!")
}
➜ main go run ./main.go
哇哇 1
哇哇 2
- 说明
- 如果return是在普通的函数,则表示跳出该函数,即不再执行函数中return后面代码,也可以理解成终止函数。
- 如果return是在main函数,表示终止main函数,也就是说终止程序。