go中的流程控制
go语言中的流程控制包含
- 顺序结构
- 按照顺序执行,不发送跳转
- 选择结构
- 依据是否满足条件,有选择的执行相应的功能
- 循环结构
- 依据条件是否满足,循环多次执行某段代码
顺序结构
就是按照代码编写的顺序来执行,中间没有任何的判断和跳转
// 代码是从上到下依次执行的
func main() {
var a int = 4
var b int32
var c float32
var ptr *int
fmt.Printf("a type is :%T\n", a)
fmt.Printf("b type is :%T\n", b)
fmt.Printf("c type is :%T\n", c)
ptr = &a
fmt.Printf("a value is : %d\n", a)
fmt.Printf("ptr is : %d\n", ptr)
fmt.Printf("ptr is : %d\n", *ptr)
}
注意:代码中使用到其他的变量,必须要在该代码上面声明
// 正确方式
func main() {
var a int = 4
var b int = 10
var c int = b + a
fmt.Printf("c type is :%d\n", c)
}
// 错误方式
func main() {
var c int = b + a
var a int = 4
var b int = 10
fmt.Printf("c type is :%d\n", c)
}
选择结构
常用的选择结构就是if-else,满足某些条件下,才能做某些事情,不满足就无法去做
if结构
对于if结构来说,就是看“条件”和“隐藏条件”
if后面的条件为真,就可以执行if代码块内的代码
if true {
fmt.Println("hello world")
}
if后面可以直接接运算符
var age int = 20
if age >= 18 {
fmt.Println("你已经成年")
}
if也支持1个初始化语句,初始化语句和判断条件以“分号”分割
if age := 20; age >= 18 {
fmt.Println("你已经成年")
}
if练习
让用户输入用户名和密码,如果用户名为admin,密码为mypass,则提示登录成功
package main
import "fmt"
//让用户输入用户名和密码,如果用户名为admin,密码为mypass,则提示登录成功
func main() {
var username string
var password string
fmt.Printf("username: ")
_, _ = fmt.Scanf("%s \n", &username)
fmt.Printf("password: ")
_, _ = fmt.Scanf("%s", &password)
if username == "admin" {
if password == "mypass" {
fmt.Println("登录成功")
}
}
}
//username: admin
//password: mypass
//登录成功
if-else结构
在使用if的时候,只有if后面的条件为true才会执行代码块里的内容,如果想要不为true时执行其他内容,就需要用到else。
if score := 80; score >=60 {
fmt.Println("及格了")
} else { // else必须在这个位置,
// 隐含了条件 score < 60
fmt.Println("没及格")
}
if嵌套
if的嵌套不宜过多,建议控制在3层内,否则代码的可读性会变差,有可能导致逻辑不清晰,出现异常bug
if xx {
if yy {
} else {
if zz {
}
}
}
举例
对学员的结业考试成绩评测
成绩>=90 :A
90>成绩>=80 :B
80>成绩>=70 :C
70>成绩>=60 :D
成绩<60 :E
func main() {
var score int
fmt.Println("请输入考试成绩:")
_, _ = fmt.Scanf("%d", &score)
if score >= 90 {
fmt.Println("A")
} else {
// 这里就隐含了条件 score < 90
if score >= 80 {
fmt.Println("B")
} else {
// 这里隐含了条件 score < 80
if score >= 70 {
fmt.Println("C")
} else {
// 这里隐含了条件 score < 70
if score >= 60 {
fmt.Println("D")
} else {
// 这里隐含了条件 score < 60
fmt.Println("E")
}
}
}
}
}
if-else if结构
我们发现上面的else里面嵌套的if判断中的else感觉多余的样子,是否可以直接在一层嵌套里直接判断呢,这就要用到if了
if xxx {
} else if yyy {
} else if zzz {
} else {
}
这样的结构,既可以让多个if-else在同一层内,又可以满足隐藏的关系
func main() {
var score int
fmt.Println("请输入考试成绩:")
_, _ = fmt.Scanf("%d", &score)
if score >= 90 {
fmt.Println("A")
} else if score >= 80 { // 这里也是一样的,隐含了score < 90的条件
fmt.Println("B")
} else if score >= 70 {
fmt.Println("C")
} else if score >= 60 {
fmt.Println("D")
} else {
fmt.Println("E")
}
}
这样的代码结构就很清晰,阅读性比上面的强
简单总结一下三种if的适用条件
- if 适用于一种情况的判断
- if-else 适用于两种情况的判断
- if-else if 适用于多种情况判断,并且判断都是对区间范围进行判断
switch结构
对于定值的判断,使用switch是一个不错的选择
switch xx {
case 10:
fmt.println("10")
case 20:
fmt.println("20")
default:
fmt.println("end")
}
switch的执行流程是:
- 程序执行到switch处,首先将变量或表达式的值计算出来
- 然后拿着这个值依次根case后面的值进行对比
- 对比成功,则结束switch
- 对比失败,进入下一个case
- 如果case都对比失败,会查看是否有default
- 有则会执行default内代码,相当于兜底的
- 无则会结束switch
switch也可以像if一样,在关键词后直接定义和使用变量
fallthrough
中文意思为“贯穿”,可以放在满足条件的case最后一行,即使下一行case不满足,也会执行里面的代码,但fallthrough不能放在最后一个case里面,因为没有可以贯穿的了
func main() {
switch score := 80; score {
case 80:
fmt.Println("80")
fallthrough
case 70:
fmt.Println("70")
case 60:
fmt.Println("60")
case 50:
fmt.Println("50")
case 40:
fmt.Println("40")
case 30:
fmt.Println("30")
}
}
输出结果为
80
70
类型转换
switch语句还可以被用于type switch(类型转换),用来判断某个interface(里面可以存储任意类型)变量里面的具体类型
switch x.(type) {
case type1:
fmt.Println("x type is type1")
case type2:
fmt.Println("x type is type2")
}
func main() {
//var x interface{} // x type is nil
var x interface{}
x = float64(3) // x type is bool or float64
switch x.(type) {
case int:
fmt.Println("x type is int")
case nil:
fmt.Println("x type is nil")
case string:
fmt.Println("x type is string")
case bool, float64:
fmt.Println("x type is bool or float64")
default:
fmt.Println("unknown")
}
}
总结
switch和case后的内容
- switch后面不写,则默认为true,下面的case则会判断最终结果是否为true
- 可以是常量、变量、一个有返回值的函数
- 在没有使用类型转换时,switch后面最终结果类型要和case最终结果类型一致
- case可以接多个表达式,只要满足其中一个即可
- case如果是常量(字面量),要求case之间不能有重复
- switch后面可以直接声明/定义一个变量,和if一样,但是不推荐这样使用,因为switch本身就是要判断这个,既然已经定义了那判断就多此一举
循环结构
循环就是重复的做同一件事情
for结构
for 初始语句;条件表达式;结束语句{
循环执行的代码
}
- 初始语句: 定义一个循环的变量,记录循环的次数
- 只执行一次
- 条件表达式:一般为循环的条件,循环多少次
- 根据条件表达式的返回值来判断是否执行循环代码(true执行,false终止)
- 结束语句:一般为改变循环条件的代码,使循环条件不再成立
- 循环代码执行完成后,会执行结束语句,对条件表达式内的变量进行修改,然后进入下一次循环的判断,也就是判断条件表达式是否成立
- 循环执行的代码:就是我们要重复做的事情
func main() {
for i := 0; i <= 10; i++ {
fmt.Println(i)
}
}
for处理顺序
func init1(n *int) int {
fmt.Println("初始化运行")
return 0
}
func expr2(n int) bool {
fmt.Printf("条件表达式运行 %d\n", n)
return n <= 10
}
func end3(n *int) *int {
fmt.Println("结束语句运行++++")
*n++
return n
}
func main() {
var i int
for init1(&i); expr2(i); end3(&i) {
fmt.Println(i)
}
}
最后的结果是
初始化运行
条件表达式运行 0
0
结束语句运行++++
条件表达式运行 1
1
结束语句运行++++
条件表达式运行 2
2
结束语句运行++++
条件表达式运行 3
3
结束语句运行++++
条件表达式运行 4
4
结束语句运行++++
条件表达式运行 5
5
结束语句运行++++
条件表达式运行 6
6
结束语句运行++++
条件表达式运行 7
7
结束语句运行++++
条件表达式运行 8
8
结束语句运行++++
条件表达式运行 9
9
结束语句运行++++
条件表达式运行 10
10
结束语句运行++++
条件表达式运行 11
for变形
初始语句、条件表达式、结束语句3种组成部分都是可选的,所以可以演化成4种不同的写法
-
// 省略初始化 func main() { i := 0 for ; i <= 10; i++ { fmt.Println(i) } }
-
// 省略条件表达式就是默认为true,形成无限循环,需要在循环代码中打破循环 func main() { i := 0 for ; ; i++ { if i > 10 { break } fmt.Println(i) } }
-
// 只保留条件判断,结束语句就在循环代码中写 // 有点像python的 while func main() { var i int for i <= 10 { fmt.Println(i) i++ } }
-
// 三种表达式都忽略,这种更像python的while func main() { var i int for { if i > 10 { break } fmt.Println(i) i++ } }
-
// 使用range来遍历 func main() { str := "1234567890" for i, value := range str { fmt.Printf("第 %d位的字符是%c \n", i, value) } }
- range可以对string、slice、array、map、channel等进行遍历
- array、slice、string返回索引和值
- map返回key和value
- channel返回通道内的值
for嵌套
for里面也可以使用for循环
for xx;xx;xx {
xxxxxx
for yy;yy;yy {
yyyyyy
}
}
示例,使用for循环打印99乘法表
func main() {
for i := 1; i <= 9; i++ {
for j := 1; j <= i; j++ {
fmt.Printf("%d*%d=%d ", 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
while和do…while的实现
Go语言中没有while和do…while语法,但是我们可以通过for循环来实现相应的效果》
while循环(先循环再做)
for {
if i>10 {
break // 跳出循环
}
i++
}
do…while(先做再循环)
for {
i++
if i>10 {
break
}
}
跳转语句
break
用于终止某个语句块的执行,用于中断当前for循环或跳出switch语句
- break默认会跳出最近的for循环
- break后面可以指定标签,跳出标签对应的for循环
lable2:
for{
for i := 0 ; i < 10 ; i++ {
if i == 2 {
break lable2
}
}
}
continue
跳出当前循环,执行下一次循环
- 用于结束本次循环,继续执行下一次循环
- 在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环
和break的区别是
- break语句无条件跳出并结束当前循环,然后执行循环后的语句
- continue语句跳过当前循环,开始执行下一次循环
goto
go语言中使用goto可以无条件转移到程序指定的行,通常配合条件语句使用,用来实现条件转移、构成循环、跳出循环体等功能
在go程序设计中一般不主张使用goto语句,以免造成程序流程的混乱,使理解和调试程序都产生困难
LABEL: statement
goto LABEL
return
在使用方法或者函数时,表示跳出所在的方法或函数
- 函数中的循环体使用return,可以直接中断循环体的运行
- return在main函数中,表示终止main函数,也就是终止程序
评论区