6.Go流程控制
前言
前面我们写的程序都是从第一行开始执行,一直执行到末尾,一行一行的顺序执行下来,这种执行结构叫顺序执行结构。
GO语言除了有顺序结构,还有选择结构,循环结构。
- 顺序结构:程序按顺序执行,不发生跳转。
- 选择结构:依据是否满足条件,有选择的执行相应功能。
- 循环结构:依据条件是否满足,循环多次执行某段代码。
下面先讲解选择结构:
1:选择结构
(1)生活中的判断场景
选择结构我们也称为判断结构。生活中的关于判断的场景也非常多,如下:
:如果跪键盘的时间大于60分钟,那么媳妇奖励我晚饭不用做了。
img
火车站安检
img
(2)开发中的判断场景
密码判断
img
重要日期判断
代码语言:javascript复制if今天是周六或者周日{
约妹子
}
if今天是情人节{
买玫瑰
}
if今天发工资{
先还信用卡的钱
if有剩余{
又可以happy了,O(∩_∩)O哈哈~
}else{
噢,no。。。还的等30天
}
}
小总结:
如果某些条件满足,才能做某件事情,而不满足时不允许做,这就是所谓的判断
1.1 if 结构
在编程中实现选择判断结构就是用if
if结构基本语法
代码语言:javascript复制if 条件判断{
代码语句
}
条件判断如果为真(true),那么就执行大括号中的语句,如果为假(false),就不执行大括号中的语句,(大家可以想一下,什么样的表达式返回的结果要么为true,要么为false),继续执行if结构后面的代码
具体案例如下:
代码语言:javascript复制var age int = 26
var b bool
b = age > 18
if b {
fmt.Println("我已经成年了")
}
上面的程序可以进行简化:
代码语言:javascript复制var age int = 26
if age > 18 {
fmt.Println("我已经成年了")
}
条件不满足时不执行
代码语言:javascript复制var age int = 16
if age > 18 {
fmt.Println("我已经成年了")
}
GO语言相比其它语言要灵活很多,下面我们看一下if的另外一种语法格式
代码语言:javascript复制// if 支持1个初始化语句,初始化语句和判断条件以分号分隔
if a := 10; a == 10 { // 条件为真,执行 {} 语句
fmt.Println("a == 10")
}
练习:让用户输入用户名和密码,如果用户名为admin,密码为mypass,则提示登录成功
代码语言:javascript复制package main
import "fmt"
func main() {
// 练习: 让用户输入用户名和密码,如果用户名为admin,密码为mypass,则提示登录成功
var userName string
var userPwd string
fmt.Println("请输入用户名: ")
fmt.Scan(&userName)
fmt.Println("请输入用户的密码:")
fmt.Scan(&userPwd)
if userName == "admin" && userPwd == "mypass" {
fmt.Println("登录成功")
}else {
fmt.Println("用户名和密码错误")
}
}
执行如下:
代码语言:javascript复制F:goProjectgo-pratice 5_流程控制>go run 01_if结构.go
请输入用户名:
admin
请输入用户的密码:
mypass
登录成功
F:goProjectgo-pratice 5_流程控制>go run 01_if结构.go
请输入用户名:
admin
请输入用户的密码:
123
用户名和密码错误
1.2 if else结构
想一想:在使用if的时候,它只能做到满足条件时要做的事情。那万一需要在不满足条件的时候,做某些事,该怎么办呢?
例如:小赵的考试成绩大于90(含)分,那么爸爸奖励他100元钱,否则的话,爸爸就让小赵跪方便面。
有同学可能会想,这道题用if
结构也可以实现。如下所示:
package main
import "fmt"
func main() {
//小赵的考试成绩大于等于90分,那么爸爸奖励他100元钱,
//否则的话,爸爸就让小赵跪方便面
var score float64
fmt.Println("输入小赵的考试成绩:")
fmt.Scan(&score)
if score >= 90 {
fmt.Println("奖励100元")
}
if score < 90 {
fmt.Println("跪方便面")
}
}
虽然以上代码可以实现,但是比较麻烦,我们可以使用更简单的方式:if else
结构如下:
代码语言:javascript复制if 条件判断{
代码语句1
}else{
代码语句2
}
首先先执行if
后面的条件判断,如果条件判断成立(结果为真),执行if
后面的代码语句1,代码语句1执行完成后,表示整个if---else--
结构结束了(else后面的代码语句2不会执行),继续执行后面的代码。
如果if
后面的条件判断不成立也就是结果为假,那么if
后面的代码语句1不会被执行,这时会执行else
后面的代码语句2,执行完后,表示整个if—else—
结构执行结束了,再执行后续的代码。
下面我们通过if---else—
结果完成上面的案例。
package main
import "fmt"
func main() {
//小赵的考试成绩大于等于90分,那么爸爸奖励他100元钱,
//否则的话,爸爸就让小赵跪方便面
var score float64
fmt.Println("输入小赵的考试成绩:")
fmt.Scan(&score)
if score >= 90 {
fmt.Println("奖励100元")
} else {
fmt.Println("跪方便面")
}
}
执行如下:
代码语言:javascript复制F:goProjectgo-pratice 5_流程控制>go run 02_if_else结构.go
输入小赵的考试成绩:
98
奖励100元
F:goProjectgo-pratice 5_流程控制>go run 02_if_else结构.go
输入小赵的考试成绩:
78
跪方便面
1.3 if 嵌套
我们上面的案例中,使用的是if-else
的基本结构,其实if-else
结构还可以进行嵌套使用。
例如:输入公交卡当前的余额,只要超过2元,就可以上公交车;如果空座位的数量大于0,就可以坐下
代码语言:javascript复制package main
import "fmt"
func main() {
// 例如:输入公交卡当前的余额,只要超过2元,就可以上公交车;如果空座位的数量大于0,就可以坐下
var money float64
fmt.Println("请输入公交卡钱数:")
fmt.Scanf("%fn", &money) // 注意:这里Scanf函数必须加上n, 否则第二个Scanf不起作用
if money >= 2 {
var seat_count int // 注意:该变量的定义位置,用到时定义赋值,节省内存空间
fmt.Println("请输入空座位的数量:")
fmt.Scanf("%d", &seat_count)
if seat_count > 0 {
fmt.Println("请坐")
} else {
fmt.Println("不好意思,您只能站着了!")
}
} else {
fmt.Println("余额不足")
}
}
执行如下:
代码语言:javascript复制F:goProjectgo-pratice 5_流程控制>go run 03_if_嵌套.go
请输入公交卡钱数:
3
请输入空座位的数量:
1
请坐
F:goProjectgo-pratice 5_流程控制>go run 03_if_嵌套.go
请输入公交卡钱数:
3
请输入空座位的数量:
0
不好意思,您只能站着了!
F:goProjectgo-pratice 5_流程控制>go run 03_if_嵌套.go
请输入公交卡钱数:
1
余额不足
以上案例在if中嵌套了if-else
结构,同理在else
也可以嵌套if-else
结构,这个要根据实际情况确定。下面我们看如下题目:
(1)对学员的结业考试成绩评测(大家考虑用if好还是用if-else好)
代码语言:javascript复制成绩>=90 :A
90>成绩>=80 :B
80>成绩>=70 :C
70>成绩>=60 :D
成绩<60 :E
我们先使用if来实现上面的问题:
代码语言:javascript复制package main
import "fmt"
func main() {
fmt.Println("请输入考试成绩:")
var score int
fmt.Scanf("%d", &score)
if score >= 90 {
fmt.Println("A")
}
if score < 90 && score >= 80 {
fmt.Println("B")
}
if score < 80 && score >= 70 {
fmt.Println("C")
}
if score < 70 && score >= 60 {
fmt.Println("D")
} else { // 注意:else 的问题
fmt.Println("E")
}
}
执行如下:
代码语言:javascript复制F:goProjectgo-pratice 5_流程控制>go run 04_if_嵌套.go
请输入考试成绩:
90
A
E
F:goProjectgo-pratice 5_流程控制>go run 04_if_嵌套.go
请输入考试成绩:
80
B
E
F:goProjectgo-pratice 5_流程控制>go run 04_if_嵌套.go
请输入考试成绩:
60
D
上面的代码我们发现最后都会输出“E”,为什么呢?
“这是因为最后一个 if-else 语句造成的,只要 if score < 70 && score >= 60 不成立,那么就会执行 else ,输出 “E”。 但是实际上,我们不希望在 score >= 90 的情况,不输出 “E” ”
解决方案如下:
image-20210423080917238
测试执行如下:
代码语言:javascript复制F:goProjectgo-pratice 5_流程控制>go run 04_if_嵌套.go
请输入考试成绩:
90
A
F:goProjectgo-pratice 5_流程控制>go run 04_if_嵌套.go
请输入考试成绩:
80
B
F:goProjectgo-pratice 5_流程控制>go run 04_if_嵌套.go
请输入考试成绩:
60
D
F:goProjectgo-pratice 5_流程控制>go run 04_if_嵌套.go
请输入考试成绩:
50
E
(2)下面我们来使用if-else 结构来解决上面的问题
案例演示如下:
代码语言:javascript复制package main
import "fmt"
func main() {
fmt.Println("请输入考试成绩:")
var score int
fmt.Scanf("%d", &score)
if score >= 90 {
fmt.Println("A")
} else {
// 所有小于90的分数都执行else,所以需要在else中继续判断(if-else结构的嵌套)
//if score < 90 && score >= 80 {
if score >= 80 {
fmt.Println("B")
} else {
//if score < 80 && score >= 70 {
if score >= 70 { // 同理这里也不需要对 < 80 进行判断
fmt.Println("C")
} else {
//if score < 70 && score >= 60 {
if score >= 60 {
fmt.Println("D")
} else {
fmt.Println("E")
}
}
}
}
}
上面的代码虽然满足了我们的需求,但是嵌套的代码非常多,可读性比较差,我们在以后的编程工作中尽量避免这种多重嵌套。
通过这道题,我们发现在这种多条件判断应用的场景中不太适合通过 if(适合一种条件判断的情况)或者是if-else(适合两种条件判断的情况或者是判断条件不是很多的场景)进行判断。
上面的题目更好的方法:if-else if结构。
1.4 if-else if 结构
基本语法如下:
代码语言:javascript复制if 条件判断{
要执行的代码段
}else if 条件判断{
要执行的代码段
}else if 条件判断{
要执行的代码段
}else if 条件判断{
要执行的代码段
}else{
要执行的代码段
}
通过以上的语法格式我们发现,可以写很多的else if结构。
具体的执行过程:
- 程序首先判断第一个if所带的小括号中的判断条件,如果条件成立,也就是返回一个true,则执行该if所带的大括号中的代码,执行完成后,立即跳出if else-if结构。
- 如果第一个if所带的判断条件不成立,也就是返回一个false,则继续向下进行判断,依次的判断每一个if所带的判断条件,如果成立,就执行该if所带的大括号中的代码,如果不成立,则继续向下判断,
- 如果每个if所带的判断条件都不成立,就看当前这个if else-if结构中是否存在else。
- 如果有else的话,则执行else中所带的代码,如果没有else,则整个 if-else if什么都不做。else可以省略。
下面我们使用该结构完成上面的案例:
代码语言:javascript复制package main
import "fmt"
func main() {
fmt.Println("请输入考试成绩:")
var score int
fmt.Scanf("%d", &score)
if score >= 90 {
fmt.Println("A")
} else if score >= 80 {
fmt.Println("B")
} else if score >= 70 {
fmt.Println("C")
} else if score >= 60 {
fmt.Println("D")
} else {
fmt.Println("E")
}
}
通过以上代码,我们发现if-else if 结构在进行多条件判断时确实比if, if-else(嵌套)要方便很多,并且结构清晰,阅读性比较强。
(1)练习:提示用户输入密码,如果密码是“88888”则提示正确,否则要求再输入一次,如果密码是“88888”则提示正确,否则提示错误,程序结束。
代码语言:javascript复制package main
import "fmt"
func main() {
// (1)练习:
// 提示用户输入密码,如果密码是“88888”则提示正确,
// 否则要求再输入一次,如果密码是“88888”则提示正确,否则提示错误,程序结束。
var pwd string
fmt.Println("请输入密码")
fmt.Scanf("%sn", &pwd)
if pwd == "88888" {
fmt.Println("密码输入正确")
} else {
fmt.Println("密码错误,请重新输入!!")
fmt.Scanf("%s", &pwd)
if pwd == "88888" {
fmt.Println("密码第二次输入正确")
} else {
fmt.Println("密码错误!!")
}
}
}
执行如下:
代码语言:javascript复制F:goProjectgo-pratice 5_流程控制>go run 07_if_else_if.go
请输入密码
66
密码错误,请重新输入!!
88888
密码第二次输入正确
(2) 练习:提示用户输入用户名,然后再提示输入密码,如果用户名是“admin”并且密码是“88888”,则提示正确,否则,如果用户名不是admin还提示用户用户名不存在,如果用户名是admin则提示密码错误。
代码语言:javascript复制// (2) 练习:
//提示用户输入用户名,然后再提示输入密码,如果用户名是“admin”并且密码是“88888”,则提示正确,
//否则,如果用户名不是admin还提示用户用户名不存在,如果用户名是admin则提示密码错误。
var name string
var pwd string
fmt.Println("请输入用户名: ")
fmt.Scanf("%sn", &name)
fmt.Println("请输入密码:")
fmt.Scanf("%s", &pwd)
// 如果用户名是“admin”并且密码是“88888”,则提示正确
if name == "admin" && pwd == "88888" {
fmt.Println("登录成功")
} else if name == "admin" && pwd != "88888"{
// 如果用户名是admin则提示密码错误
fmt.Println("密码错误")
} else {
fmt.Println("用户名和密码都错误")
}
执行如下:
代码语言:javascript复制F:goProjectgo-pratice 5_流程控制>go run 07_if_else_if.go
请输入用户名:
hello
请输入密码:
hell
用户名和密码都错误
F:goProjectgo-pratice 5_流程控制>go run 07_if_else_if.go
请输入用户名:
admin
请输入密码:
123
密码错误
F:goProjectgo-pratice 5_流程控制>go run 07_if_else_if.go
请输入用户名:
admin
请输入密码:
88888
登录成功
用于该题的判断条件比较多,所以这里使用的是if-else if结构。
(3) 练习:提示用户输入年龄,如果大于等于18,则告知用户可以查看,如果小于10岁,则告知不允许查看,如果大于等于10岁并且小于18,则提示用户是否继续查看(yes、no),如果输入的是yes则提示用户请查看,否则提示"退出,你放弃查看"。
首先我们分析一下该题的条件:
- 第一种情况:年龄>=18
- 第二种情况:年龄<10
- 第三种情况:年龄>=10&&<18,如果满足该条件,则继续判断用户输入的内容是“yes”还是”no”
根据以上分析,使用if-else if 结构比较容易实现。具体案例展示如下:
代码语言:javascript复制// (3) 练习:提示用户输入年龄,如果大于等于18,则告知用户可以查看,
//如果小于10岁,则告知不允许查看,
//如果大于等于10岁并且小于18,则提示用户是否继续查看(yes、no),
//如果输入的是yes则提示用户请查看,否则提示"退出,你放弃查看"。
var age int
fmt.Println("请输入年龄:")
fmt.Scanf("%dn", &age)
if age >= 18 {
// 如果大于等于18,则告知用户可以查看
fmt.Println("可以查看信息")
} else if age < 10 {
//如果小于10岁,则告知不允许查看,
fmt.Println("不允许查看")
} else if age >= 10 && age < 18{
//如果大于等于10岁并且小于18,则提示用户是否继续查看(yes、no)
var input string
fmt.Println("是否继续查看(yes、no)")
fmt.Scanf("%s", &input)
if input == "yes" {
fmt.Println("用户请查看")
} else {
fmt.Println("退出,你放弃查看")
}
}
执行如下:
代码语言:javascript复制F:goProjectgo-pratice 5_流程控制>go run 07_if_else_if.go
请输入年龄:
16
是否继续查看(yes、no)
yes
用户请查看
F:goProjectgo-pratice 5_流程控制>go run 07_if_else_if.go
请输入年龄:
no
不允许查看
F:goProjectgo-pratice 5_流程控制>go run 07_if_else_if.go
请输入年龄:
18
可以查看信息
F:goProjectgo-pratice 5_流程控制>go run 07_if_else_if.go
请输入年龄:
9
不允许查看
总结:我们通过前面的案例讲解,大家应该能够总结出if结构,if-else结构和if-else if结构应用的场景.
- if结构适合:一种的判断
- if-else结构适合:两种情况的判断
- if-else if 结构适合: 多种情况判断,并且判断都是对区间中的数据进行判断(例如:考试成绩)
1.5 switch 结构
下面我们开始讲解选择中的另外一个结构就是switch结构。
在讲解switch结构之前,我们先来看如下问题:
李四的年终工作评定,如果定为A级,则工资涨500元,如果定为B级,则工资涨200元,如果定为C级,工资不变,如果定为D级工资降200元,如果定为E级工资降500元.
设李四的原工资为5000,请用户输入李四的评级,然后显示李四来年的工资.
大家看到如上题目,肯定想到的是用 if-else if
结构来实现,那么具体案例实现如下:
package main
import "fmt"
func main() {
/**
李四的年终工作评定,
- 如果定为A级,则工资涨500元,
- 如果定为B级,则工资涨200元,
- 如果定为C级,工资不变,
- 如果定为D级工资降200元,
- 如果定为E级工资降500元.
设李四的原工资为5000,请用户输入李四的评级,然后显示李四来年的工资.
*/
var salary int = 5000 // 原定工资
var level string
fmt.Println("请输入李四的年终评定:")
fmt.Scanf("%s", &level)
if level == "A" {
// 如果定为A级,则工资涨500元
salary = 500
} else if level == "B" {
// 如果定为B级,则工资涨200元
salary = 200
} else if level == "C" {
// 如果定为C级,工资不变
} else if level == "D" {
// 如果定为D级工资降200元
salary -= 200
} else if level == "E" {
// 如果定为E级工资降500元
salary -= 500
} else {
fmt.Println("输入错误,程序推迟!!")
}
fmt.Println("李四来年的工资是: ", salary)
}
虽然以上代码实现了我们的需求,但是我们发现了一个问题,如果输入其它字符(例如:输入字符T),我们发现最终的结果不仅输出了“输入错误,程序退出”,同时还输出了“李四来年的工资是:5000”。如果输入错误了,这句话是不应该输出的,那么应该怎样进行处理呢?
代码语言:javascript复制package main
import "fmt"
func main() {
/**
李四的年终工作评定,
- 如果定为A级,则工资涨500元,
- 如果定为B级,则工资涨200元,
- 如果定为C级,工资不变,
- 如果定为D级工资降200元,
- 如果定为E级工资降500元.
设李四的原工资为5000,请用户输入李四的评级,然后显示李四来年的工资.
*/
var salary int = 5000 // 原定工资
var level string
fmt.Println("请输入李四的年终评定:")
fmt.Scanf("%s", &level)
var flag bool = true // 设置是否打印工资的信息
if level == "A" {
// 如果定为A级,则工资涨500元
salary = 500
} else if level == "B" {
// 如果定为B级,则工资涨200元
salary = 200
} else if level == "C" {
// 如果定为C级,工资不变
} else if level == "D" {
// 如果定为D级工资降200元
salary -= 200
} else if level == "E" {
// 如果定为E级工资降500元
salary -= 500
} else {
flag = false // 当错误,则不打印工资信息
fmt.Println("输入错误,程序推迟!!")
}
// 当输入正确,才打印工资信息
if flag {
fmt.Println("李四来年的工资是: ", salary)
}
}
通过上面的代码,我们实际上是定义了一个bool类型的变量 flag,默认值为true,当输入评定级别错误时,将其改为false.最后在输出工资时,做了判断,如果条件成立表示输入了正确的评定级别,所以输出对应的工资,否则不输出工资。(这种技巧,需要大家好好体会一下)
我们前面在讲解if-else if结构时讲过,该结构适合什么场合:1.多条件判断,2:区间性的数据判断。但是我们看一下该案例,是否是对区间性的数据进行判断呢?不是,而是定值判断,也就是对一个固定值的判断。
对这种固定值的判断推进使用switch-case结构。
(1) switch-case结构语法如下:
代码语言:javascript复制switch 变量或者表达式的值{
case 值1:
要执行的代码
case 值2:
要执行的代码
case 值3:
要执行的代码
………………………………
default:
要执行的代码
}
switch-case结构的执行流程:
程序执行到switch处,首先将变量或者表达式的值计算出来,然后拿着这个值依次跟每个case后面所带的值进行匹配,一旦匹配成功,则执行该case所带的代码,执行完成后,跳出switch-case结构。如果,跟每个case所带的值都不匹配。就看当前这个switch-case结构中是否存在default,如果有default,则执行default中的语句,如果没有default,则该switch-case结构什么都不做。
基本案例演示如下:
代码语言:javascript复制package main
import "fmt"
func main() {
var score int = 30
switch score {
case 90:
fmt.Println("优秀")
case 80:
fmt.Println("良好")
case 70:
fmt.Println("一般")
case 60:
fmt.Println("及格")
default:
fmt.Println("不及格")
}
}
GO语言中switch-case结构中,case后面默认自带break(终止程序执行),这是与其它语言不同的地方。
另外一种语法格式如下:
代码语言:javascript复制// 另外一种语法格式如下:
switch score := 78; score { // 初始化变量 score 的同时,将其设置为 case 变量
case 90:
fmt.Println("优秀")
case 80:
fmt.Println("良好")
case 70:
fmt.Println("一般")
case 60:
fmt.Println("及格")
default:
fmt.Println("不及格")
}
注意:某个case 后面跟着的代码执行完毕后,不会再执行后面的case,而是跳出整个switch结构, 相当于每个case后面都跟着break(终止),但是如果我们想执行完成某个case后,强制执行后面的case,可以使用fallthrough
。
下面我们用switch-case结构来实现上面的案例,示例如下:
代码语言:javascript复制// fallthrough
/**
李四的年终工作评定,
- 如果定为A级,则工资涨500元,
- 如果定为B级,则工资涨200元,
- 如果定为C级,工资不变,
- 如果定为D级工资降200元,
- 如果定为E级工资降500元.
设李四的原工资为5000,请用户输入李四的评级,然后显示李四来年的工资.
*/
var salary int = 5000 // 原定工资
var level string
fmt.Println("请输入李四的年终评定:")
fmt.Scanf("%s", &level)
var flag bool = true // 设置是否打印工资的信息
switch level {
case "A":
// 如果定为A级,则工资涨500元
salary = 500
case "B":
// 如果定为B级,则工资涨200元
salary = 200
case "C":
// 如果定为C级,工资不变
fallthrough
case "D":
// 如果定为D级工资降200元
salary -= 200
case "E":
// 如果定为E级工资降500元
salary -= 500
default:
flag = false // 当错误,则不打印工资信息
fmt.Println("输入错误,程序推迟!!")
}
// 当输入正确,才打印工资信息
if flag {
fmt.Println("李四来年的工资是: ", salary)
}
1.6 if-else if与switch的比较
其实通过上面的案例,我们发现switch能够实现的,我们用if-else if也可以实现,那么反过来呢,if-else if能实现的,我们使用switch能否实现呢?接下来将我们前面用if-else if实现的“考试成绩评定”这道题用switch来实现。
代码语言:javascript复制fmt.Println("请输入考试成绩:")
var score int
fmt.Scanf("%d", &score)
switch { // 这里没有写条件
case score >= 90: // 在case写判断语句
fmt.Println("A")
case score >= 80:
fmt.Println("B")
case score >= 70:
fmt.Println("C")
case score >= 60:
fmt.Println("D")
default:
fmt.Println("E")
}
总结:
- 相同点:都可以实现多分支结构
- 不同点(根据个人习惯进行选择): if-else if: 可以处理范围 switch: 一般用于等值比较
下面我们通过一个练习题,将if-else和switch结构进行综合应用
练习:请用户输年份,再输入月份,输出该月的天数.(结合之前如何判断闰年来做)
代码语言:javascript复制package main
import "fmt"
func main() {
//请用户输年份,再输入月份,输出该月的天数.
var year int //表示年份
var month int //表示月份
var day int
fmt.Println("请输入年份")
fmt.Scanf("%dn", &year)
fmt.Println("请输入月份")
fmt.Scanf("%d", &month)
//判断月份的取值范围
if month >= 1 && month <= 12 {
switch month{
case 1:
fallthrough
case 3:
fallthrough
case 5:
fallthrough
case 7:
fallthrough
case 8:
fallthrough
case 10:
fallthrough
case 12:
day = 31
case 2: //需要判断是否为闰年
if (year@0==0) || (year%4==0 && year0!=0){
day = 29
} else{
day = 28
}
default:
day = 30
}
fmt.Printf("%d年%d月共%d天", year, month, day)
} else {
fmt.Println("月份输入错误!!")
}
}
通过上面的案例,我们发现switch结构和if-else结构是可以结合来使用的,可以根据具体的问题具体分析,灵活来应用。
2:循环结构
2.1 循环概念
所谓的循环就是重复的做同一件事情,我们先从生活的角度来理解一下循环。
img
打印100份试卷
李四这次考试又粗心了,爸爸让他写1000遍“下次考试一定要细心”.
在编程中,我们也会经常遇到循环的问题,例如:
跟媳妇承认错误,说一万遍"媳妇儿,我错了"
代码语言:javascript复制fmt.Println("媳妇儿,我错了")
fmt.Println("媳妇儿,我错了")
fmt.Println("媳妇儿,我错了")
…………………………………写一万遍 fmt.Println("媳妇儿,我错了")
2.2 基本语法结构
在GO语言中,我们有专门实现这种循环的结构就是for结构(GO语言中只有for循环结构,没有while,do-while结构),
基本语法结构如下:
代码语言:javascript复制for 表达式1;表达式2;表达式3{
循环体
}
- 表达式1:定义一个循环的变量,记录循环的次数
- 表达式2:一般为循环条件,循环多少次
- 表达式3:一般为改变循环条件的代码,使循环条件终有一天不再成立
- 循环体:重复要做的事情。
下面我们用for循环结构输出10遍“媳妇儿,我错了”。
代码语言:javascript复制func main() {
// 用for循环结构输出10遍“媳妇儿,我错了”
var i int
for i = 1; i <= 10; i {
fmt.Println("媳妇儿,我错了")
}
}
以上代码执行的顺序:
- 首先执行表达式1(
i = 1
)进行初始化,然后执行表达式2(i <= 10
),判断循环条件是否成立,如果表达式2返回的结果为true,则执行循环体。 - 当执行完循环体后,执行表达式3(
i
),然后执行表达式2(这时不会在执行表达式1)继续判断循环条件是否成立, 如果成立则继续执行循环体,如果不成立,则跳出for循环。
思考:将上面的代码中,变量i的初始值赋值为0,那么表达式2怎样修改?
我们也可以将语法进行简化如下:
代码语言:javascript复制// 用for循环结构输出10遍“媳妇儿,我错了”
//var i int
for i := 0; i < 10; i {
fmt.Println("媳妇儿,我错了")
}
2.3 练习
(2.3.1)求1—100之间所有的整数之和。
代码语言:javascript复制// (2.3.1)求1—100之间所有的整数之和。
var sum int // 定义一个变量,存储累加的和
for i := 1; i <= 100; i {
sum = i
}
fmt.Println("累加的和为: ", sum)
执行如下:
代码语言:javascript复制累加的和为: 5050
(2.3.2)求1—100之间的耦合之和
代码语言:javascript复制// (2.3.2)求1—100之间的耦合之和
var sum int // 定义一个变量,存储累加的和
for i := 1; i <= 100; i {
if i%2 == 0 {
sum = i
}
}
fmt.Println("求1—100之间的耦合之和: ", sum)
执行如下:
代码语言:javascript复制求1—100之间的耦合之和: 2550
(2.3.3)输入班级人数,然后依次输入学员成绩,计算班级学员的平均成绩和总成绩
分析:首先让用户输入班级的人数,例如10人
循环变量:初始值为1
循环条件:循环的次数小于班级人数
循环体:提示用户输入学生的成绩,然后接收,接收完成后,累加到总成绩中。
具体案例如下:
代码语言:javascript复制// (2.3.3)输入班级人数,然后依次输入学员成绩,计算班级学员的平均成绩和总成绩
var count int
var score float64
var sum float64
fmt.Println("请输入班级人数:")
fmt.Scanf("%dn", &count)
// 通过循环统计综合
for i := 1; i <= count; i {
fmt.Printf("请输入%d学生的成绩: ", i)
fmt.Scanf("%fn", &score)
sum = score
}
fmt.Printf("班级总人数为: %d, 总成绩为: %f, 平局成绩: %f", count, sum, sum/float64(count))
执行如下:
代码语言:javascript复制请输入班级人数:
3
请输入1学生的成绩: 99
请输入2学生的成绩: 65
请输入3学生的成绩: 89
班级总人数为: 3, 总成绩为: 253.000000, 平局成绩: 84.333333
(2.3.4)2006年培养学员80000人,每年增长25%,请问按此增长速度,到哪一年培训学员人数将达到20万人
分析:循环条件:学员人数>20万人时,结束整个循环,否则继续循环。(先将循环条件分析清楚,并且写完代码,然后在分析循环体)
循环体:对年份进行累加
代码语言:javascript复制// (2.3.4)2006年培养学员80000人,每年增长25%,请问按此增长速度,到哪一年培训学员人数将达到20万人
var people float64
var year int = 2006
for people = 80000; people <= 200000 ; people = people * 1.25 {
year = 1
}
fmt.Printf("到%d年培训学院人数将达到20万人", year)
执行如下:
代码语言:javascript复制到2011年培训学院人数将达到20万人
注意:第三个表达式的变化。
(2.3.5)找出100-999间的水仙花数
分析:水仙花数指的就是 这个百位数字的,百位的立方 十位的立方 个位的立方 == 当前这个百位数字
例如: 153这个数字 百位数为1, 十位数为5,个位数为3
那么1的立方是1, 5的立方是125, 3的立方是27。
那么1 125 27正好是153
所以这道题的关键是我们怎样获取某个三位数字中的百位,十位,个位。
方法如下:
代码语言:javascript复制百位:153/100
十位:1530/10
个位:153
具体案例如下:
代码语言:javascript复制// (2.3.5)找出100-999间的水仙花数
var h int // 百位数
var t int // 十位数
var u int // 个位数
for i := 100; i <= 999; i {
h = i / 100
t = i % 100 / 10
u = i % 10
if (h*h*h) (t*t*t) (u*u*u) == i {
fmt.Println("水仙花数有:", i)
}
}
执行如下:
代码语言:javascript复制水仙花数有: 153
水仙花数有: 370
水仙花数有: 371
水仙花数有: 407
2.4 跳转语句
关于GO语句中的跳转语句,有break,continue,goto(与函数结合使用)
下面我们先来讲解break.
根据前面的案例,我们发现,循环必须指定循环条件,在满足循环条件的时候执行循环,如果不满足循环的条件,可以跳出整个循环。但是如果,我们没有指定循环条件,那么循环就成了死循环,所谓的死循环指的就是一直循环,跳不出来了。
怎样构建死循环呢?语法如下:
代码语言:javascript复制// 死循环
for {
fmt.Println("死循环.....")
}
执行如下:
代码语言:javascript复制死循环.....
死循环.....
死循环.....
死循环.....
死循环.....
死循环.....
死循环.....
...
死循环(无限循环)的语法非常简单,就是什么循环条件也没有写。
下面我们来看一下,关于死循环的应用场景
(2.4.1)案例:要求用户输入用户名和密码,只要不是admin、888888就一直提示用户名,密码错误,请重新输入。
分析:该题我们怎样构建循环条件呢?
按照我们以前的做法,很难构建循环条件,那么我们可以使用死循环来做,但是,我们要在用户输入正确的用户名和密码的时候跳出整个循环,那么我们应该怎样强制的跳出死循环呢?我们可以使用break关键字。
break的作用就是跳出本次循环
案例演示如下:
代码语言:javascript复制// (2.4.1)案例:要求用户输入用户名和密码,只要不是admin、888888就一直提示用户名,密码错误,请重新输入。
var userName string
var userPwd string
for {
fmt.Println("请输入用户名: ")
fmt.Scanf("%sn", &userName)
fmt.Printf("请输入密码:")
fmt.Scanf("%sn", &userPwd)
//判断用户名,密码输入是否正确
if userName == "admin" && userPwd == "888888" {
fmt.Println("登录成功")
break // 跳出循环
} else {
fmt.Println("用户名密码错误,请重新输入!!")
}
}
执行如下:
image-20210426002350305
通过以上案例演示,我们发现当程序执行到break语句时,会跳出for循环。
思考: 现在将上面的题目的需求在改动一下,加上以下条件”用户名密码输入错误,最多输错3次,超过3次,提示输入错误信息次数太多,并且结束整个程序”,那么该程序怎样修改呢?
案例演示如下:
代码语言:javascript复制// (2.4.1)案例:要求用户输入用户名和密码,只要不是admin、888888就一直提示用户名,密码错误,请重新输入。
var userName string
var userPwd string
var count int // 记录错误次数
for {
fmt.Println("请输入用户名: ")
fmt.Scanf("%sn", &userName)
fmt.Printf("请输入密码:")
fmt.Scanf("%sn", &userPwd)
//判断用户名,密码输入是否正确
if userName == "admin" && userPwd == "888888" {
fmt.Println("登录成功")
break // 跳出循环
} else {
count // 输入错误,进行累加
if count >= 3 {
//当错误大于等于3次,则提示错误太多,停止循环
fmt.Println("输入错误次数太多!")
break // 跳出循环
}
fmt.Println("用户名密码错误,请重新输入!!")
}
}
执行如下:
image-20210426082902595
(2.4.2)老师问学生,这道题你会做了吗?如果学生答"会了(y)",则可以放学.如果学生不会做(n),则老师再讲一遍,再问学生是否会做了......
问题1:直到学生会为止,才可以放学.
问题2:直到学生会或老师给他讲了10遍还不会,都要放学
分析:这道题与上一道非常类似,大家可以自己思考做一下。
(2.4.3)循环录入5个人的年龄并计算平均年龄,如果录入的数据出现负数或大于100的数,立即停止输入并报错
分析: 定义一个变量来接收用户输入的年龄,同时还要定义一个变量来保存5个人的年龄之和。
然后大家思考一下,要解决该问题是否还要用死循环呢?不需要,因为这里已经规定了要输入5个人的年龄,所以我们可以循环5次
但是只要输入了负数或大于100的数,我们可以使用break强制终止程序。
代码语言:javascript复制// (2.4.3)循环录入5个人的年龄并计算平均年龄,如果录入的数据出现负数或大于100的数,立即停止输入并报错
var age int
var sum int
var b bool = true
for i := 1; i <= 5; i {
fmt.Printf("请输入第%d个人的年龄: n", i)
fmt.Scanf("%dn", &age)
if age < 0 || age > 100 {
fmt.Println("输入错误!!")
b = false
break
}
sum = age
}
if b {
fmt.Println("5个人的总年龄是", sum)
}
正确执行如下:
image-20210426083804788
错误执行如下:
image-20210426083826723
(2.4.4)continue语句
前面我们已经讲解完成了break,下面我们来说一下continue语句。
continue的作用是:立即结束本次循环,判断循环条件,如果成立,则进入下一次循环,否则退出循环.
基本语法:
代码语言:javascript复制// continue语句
for i := 1; i <= 5; i {
if i == 2 {
continue
}
fmt.Println("i的值为:", i)
}
执行如下:
代码语言:javascript复制i的值为: 1
i的值为: 3
i的值为: 4
i的值为: 5
“执行过程: 当i的值为1时,判断循环条件,满足循环条件(i<=5),进入循环体,执行if判断,发现条件不满足,不执行continue,直接打印,第一次循环结束,进入第二次循环,这时变量i的值为2, 满足循环条件,进入循环体,执行if判断,发现满足条件,执行continue,continue的作用:结束本次循环,也就是不在执行后面的代码(不管后面有多少行代码都不在执行),直接跳转到for,执行for循环的第三个表达式,让i的值进行加1操作,这时i变量的值变成3,判断一下是否满足循环条件,满足(i<=5),进入循环体,开始执行,以此类推。最终输出结果:1,3,4,5 ”
(2.4.5)练习:用continue实现计算1到100(含)之间的除了能被7整除之外所有整数的和。(该题也可以使用其它方式来实现)
代码语言:javascript复制// (2.4.5)练习:用continue实现计算1到100(含)之间的除了能被7整除之外所有整数的和。(该题也可以使用其它方式来实现)
var sum int
for i := 1; i <= 100 ; i {
if i%7 == 0 {
continue
}
sum = i
}
fmt.Println(sum)
执行如下:
代码语言:javascript复制4315
(2.4.6)循环嵌套
我们在前面学习选择结构时,讲解过关于选择结构的嵌套,同理循环结构也有嵌套。
基本使用结构如下:
代码语言:javascript复制var i int
var j int
for i = 1; i <= 10; i {
for j = 1; j <= 10; j {
}
}
在屏幕上输出如下图所示的乘法口诀表
如图所示:
image-20210426084706205
代码语言:javascript复制var i int
var j int
for i = 1; i <= 10; i {
for j = 1; j <= 10; j {
fmt.Printf("%d*%d=%dt",i,j,i*j)
}
fmt.Println("")
}
输出以下结构的乘法口诀表:
image-20210426084819555
代码语言:javascript复制var i int
var j int
for i = 1; i <= 10; i {
for j = 1; j <= i; j {
fmt.Printf("%d*%d=%dt",i,j,i*j)
}
fmt.Println("")
}
(2.4.7)输出以下图形
image-20210426084913756
代码语言:javascript复制var i int
var j int
for i = 1; i <= 10; i {
for j = 1; j <= i; j {
fmt.Printf("*")
}
fmt.Println("")
}
注意:尽量不要多层嵌套,性能比较低。