6.Go流程控制

2022-01-17 10:39:49 浏览数 (1)

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-pratice5_流程控制>go run 01_if结构.go
请输入用户名:
admin
请输入用户的密码:
mypass
登录成功

F:goProjectgo-pratice5_流程控制>go run 01_if结构.go
请输入用户名:
admin
请输入用户的密码:
123
用户名和密码错误

1.2 if else结构

想一想:在使用if的时候,它只能做到满足条件时要做的事情。那万一需要在不满足条件的时候,做某些事,该怎么办呢?

例如:小赵的考试成绩大于90(含)分,那么爸爸奖励他100元钱,否则的话,爸爸就让小赵跪方便面。

有同学可能会想,这道题用if结构也可以实现。如下所示:

代码语言:javascript复制
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—结果完成上面的案例。

代码语言:javascript复制
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-pratice5_流程控制>go run 02_if_else结构.go
输入小赵的考试成绩:
98
奖励100元

F:goProjectgo-pratice5_流程控制>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-pratice5_流程控制>go run 03_if_嵌套.go
请输入公交卡钱数:
3
请输入空座位的数量:
1
请坐

F:goProjectgo-pratice5_流程控制>go run 03_if_嵌套.go
请输入公交卡钱数:
3
请输入空座位的数量:
0
不好意思,您只能站着了!

F:goProjectgo-pratice5_流程控制>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-pratice5_流程控制>go run 04_if_嵌套.go
请输入考试成绩:
90
A
E

F:goProjectgo-pratice5_流程控制>go run 04_if_嵌套.go
请输入考试成绩:
80
B
E

F:goProjectgo-pratice5_流程控制>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-pratice5_流程控制>go run 04_if_嵌套.go
请输入考试成绩:
90
A

F:goProjectgo-pratice5_流程控制>go run 04_if_嵌套.go
请输入考试成绩:
80
B

F:goProjectgo-pratice5_流程控制>go run 04_if_嵌套.go
请输入考试成绩:
60
D

F:goProjectgo-pratice5_流程控制>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-pratice5_流程控制>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-pratice5_流程控制>go run 07_if_else_if.go
请输入用户名:
hello
请输入密码:
hell
用户名和密码都错误

F:goProjectgo-pratice5_流程控制>go run 07_if_else_if.go
请输入用户名:
admin
请输入密码:
123
密码错误

F:goProjectgo-pratice5_流程控制>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-pratice5_流程控制>go run 07_if_else_if.go
请输入年龄:
16
是否继续查看(yes、no)
yes
用户请查看

F:goProjectgo-pratice5_流程控制>go run 07_if_else_if.go
请输入年龄:
no
不允许查看

F:goProjectgo-pratice5_流程控制>go run 07_if_else_if.go
请输入年龄:
18
可以查看信息

F:goProjectgo-pratice5_流程控制>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结构来实现,那么具体案例实现如下:

代码语言: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)

   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("")
} 

注意:尽量不要多层嵌套,性能比较低。

0 人点赞