概述
程序中,程序运行的流程控制决定程序如何执行,包含顺序控制、分支控制和循环控制三类。
一、顺序控制
程序从上到下逐行执行,中间没有任何判断和跳转。
二、分支控制 if-else
分支控制就是让程序有选择的执行,包含单分支,双分支和多分支:
1. 单分支
基本语法为:条件表达式可以加括号(),但是官方不推荐!
// 条件表达式为真时,执行{}中的代码
// {}必须有
if 条件表达式 {
执行代码块
}
示例:编写一个程序,输入人的年龄,如果年龄大于18岁,则输出“你成年了!”。
package main
import (
"fmt"
)
func main() {
var age int
fmt.Println("请输入年龄: ")
fmt.Scanln(&age)
// if 的条件判断语句里允许声明一个变量,该变量的作用域只能在该条件逻辑块内
// if age := 20; age > 18 {
// 执行代码块
// }
if age > 18 {
fmt.Println("你成年了!")
}
}
1) 使用细节
Golang中,if 的条件判断语句里允许声明一个变量,该变量的作用域只能在该条件逻辑块内。注意:{} 必须要!!!
if age := 20; age > 18 {
fmt.Println("你成年了!")
}
2. 双分支
基本语法为:
// 条件表达式为真时,执行{}中的代码
// {}必须有
if 条件表达式 {
执行代码块1
} else {
执行代码块2
}
改进上面的代码,条件 age > 18 不成立时,输出"你还是个小屁孩!":
package main
import (
"fmt"
)
func main() {
var age int
fmt.Println("请输入年龄: ")
fmt.Scanln(&age)
if age > 18 {
fmt.Println("你成年了!")
} else {
fmt.Println("你还是个小屁孩!")
}
}
3. 多分支
基本语法为:
// 条件表达式为真时,执行{}中的代码
// {}必须有
if 条件表达式1 {
执行代码块1
} else if 条件表达式2 {
执行代码块2
} else if 条件表达式3 {
执行代码块3
} ···
} else {
执行代码块n
}
示例:求 a x 2 + b x + c = 0 ax^2 + bx + c = 0 ax2+bx+c=0方程的根。
package main
import (
"fmt"
"math"
)
func main() {
var a, b, c float64
var x1, x2, x float64
fmt.Println("请输入a, b, c: ")
fmt.Scanf("%f %f %f", &a, &b, &c)
if (b * b - 4 * a * c) > 0 {
x1 = (-b + math.Sqrt(b * b - 4 * a * c)) / (2 * a)
x2 = (-b - math.Sqrt(b * b - 4 * a * c)) / (2 * a)
fmt.Println("该方程有两个解, 解为 x1 = ", x1, "x2 = ", x2)
} else if (b * b - 4 * a * c) == 0 {
x = -b / (2 * a)
fmt.Println("该方程仅有一个解, 解为 x = ", x)
} else {
fmt.Println("该方程无解!")
}
}
输出结果为:
注意:嵌套分支不宜太多,尽量控制在三层以内。
三、switch 分支结构
1. 语法结构
Golang中,匹配项后面不需要加break,默认执行完其中一个 case 或 default 之后结束 switch。基本语法为:
switch 表达式 {
// case 后的表达式可以有多个,使用逗号隔开
// 表达式 == 表达式1 || 表达式 == 表达式2 || ···
// 则执行语句块1
case 表达式1, 表达式2, ... :
语句块1
case 表达式3, 表达式4, ... :
语句块2
default:
语句块
}
switch 执行的流程: 先执行表达式,得到值,然后和 case 的表达式进行比较,若相等,则完成匹配并执行对应的 case 的语句块,然后结束 switch。
package main
import (
"fmt"
_ "math"
)
func main() {
var ch byte
fmt.Println("请输入一个字符 a-g: ")
fmt.Scanf("%c", &ch)
switch ch {
case 'a' :
fmt.Println("星期一") // ch == 'a',执行 case 'a'。
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("错误!!!")
}
}
输出结果为:
2. 使用细节
1) case
1、case 后面是一个表达式:常量、变量、有返回值的函数等;
2、case后表达式的值的数据类型要和switch的表达式的数据类型一致;
3、case 后面不加break;
4、case后面的表达式如果是常量,要求不能重复。
2) switch
1、switch后面也可以不带表达式,类似于if-else分支;
var age int = 10
switch {
case age == 10: // 表达式也可以为:age > 5 && age < 15,age > 5 等。
语句块1
case age == 20:
语句块2
default:
语句块3
}
2、switch后面也可以直接 声明/定义 一个变量 ( switch age := 20; {} ),以分号结束,但是不推荐!!!
3、switch穿透:fallthrough,case 语句块后增加fallthrough,继续执行下一个case。
package main
import (
"fmt"
_ "math"
)
func main() {
var age int = 20
switch {
case age > 5 && age < 25:
fmt.Println("年龄处于范围内!")
fallthrough
case age == 50:
fmt.Println("age = ", age)
default:
fmt.Println("哦豁, 穿透失败! 检查是否添加关键字fallthrough!")
}
}
输出结果为:
注意穿透的有趣现象:穿透之后的下一个 case 表达式仿佛失效了!
4、type switch:用于判断某个 interface (接口) 变量中实际指向的变量类型。
3. 练习
1) 将小写类型的char型转换为大写,只转换a, b, c, d, e,其他的输出other。
package main
import (
"fmt"
)
func main() {
var ch byte
fmt.Println("请输入小写字母:")
fmt.Scanf("%c", &ch)
switch ch {
case 'a', 'b', 'c', 'd', 'e':
fmt.Printf("%c 的大写字母是 %c", ch, ch - 32)
default:
fmt.Println("other!")
}
}
输出结果为:
2) 成绩>60,输出“合格”;<60,输出“不合格”。输入的成绩不能大于100。
package main
import (
"fmt"
)
func main() {
var score int
fmt.Println("请输入分数:")
fmt.Scanln(&score)
/*******************************
switch int(score / 60) {
case 1:
fmt.Println("合格")
case 0:
fmt.Println("不合格")
default:
fmt.Println("输入成绩大于100!!!")
}
********************************/
switch {
case score > 60 && score <= 100:
fmt.Println("合格")
case score < 60:
fmt.Println("不合格")
default:
fmt.Println("输入成绩大于100!!!")
}
}
输出结果为:
4. switch和if的比较
1) 什么情况下使用 switch
判断的具体数值不多,且符合整数、浮点数、字符、字符串这几种类型。
2) 什么情况下使用 if
对区间判断和结果为bool类型的判断,使用 if。
四、循环控制
1. for 循环
1) 语法结构
基本语法结构为:
for 循环变量初始化; 循环条件; 循环变量迭代 {
循环操作语句
}
// for example
for i := 1; i <= 10; i++ {
fmt.Println("Li")
}
四要素: 循环变量初始化;循环条件;循环操作语句(循环体);循环变量迭代。
2) 使用细节
1、循环条件是一个返回bool值的表达式;
2、for循环的第二种使用方式:将变量初始化和变量迭代写到其他位置。
循环变量初始化
for 循环条件 {
// 循环操作语句
循环变量迭代
}
// for example
i := 1
for i <= 10 {
fmt.Println("Li")
i++
}
3、for 循环的第三种使用方式:
for { // 等价于 for ; ; {
// 循环体
}
等价于 for ; ; {},是一个无限循环,通常配合break使用。
4、Golang提供for-range方法,方便遍历字符串和数组:
// 使用for-range遍历字符串
package main
import (
"fmt"
)
func main() {
str := "hello, Chongqing"
for index, val := range str {
fmt.Printf("index = %d, val = %cn", index, val)
}
}
// 传统遍历方式
str := "hello, Chongqing"
for index := 1; index <= len(str); index++ {
fmt.Printf("index = %d, val = %cn", index, str[index - 1])
}
for-range 的输出结果去下图所示,其中 index 保存 val 对应的下标:
注意:
-
如果字符串 str 中含有中文,传统的遍历方式会出现乱码错误,因为传统方式按照字节来遍历字符串,Golang中使用 UTF-8 编码,一个英文字符对应1个字节,一个中文字符对应 3 个字节,因此出现乱码。 解决方法:将 str 转成 [ ]rune(str) 切片,即 str2 = [ ]rune(str)。
-
for-range按照字符来遍历,字符串有中文也不会出现乱码。
2. while和do-while的实现
Golang 中没有 while 和 do-while 语法,可以通过 for 循环实现。
1) for循环实现while循环
// 使用for循环实现while循环
循环变量初始化
for {
if 循环条件表达式 {
break // 跳出for循环
}
循环体
循环变量迭代
}
注意:
- for {} 循环是无限循环;
- break 语句的作用是跳出 for 循环。
2) for循环实现do-while循环
// 使用 for 循环实现 do-while 循环
循环变量初始化
for {
循环体
循环变量迭代
if 循环条件表达式 {
break // 跳出for循环
}
}
注意:
- 先执行,再判断,至少执行一次;
- break 语句的作用是跳出 for 循环。
3. 循环嵌套 (多重循环)
1) 案例一
统计3个班的成绩情况,每个班有5名学生,求出各个班的平均分和所有班的平均分,从键盘输入学生成绩。
package main
import (
"fmt"
)
func main() {
var classNum int = 3
var stuNum int = 5
var total_sum float64 = 0.0
for j:= 1; j <= classNum; j++{
var sum float64 = 0.0
for i := 1; i <= stuNum; i++ {
var score float64
fmt.Printf("请输入第%d个班的第%d个学生的成绩: ", j, i)
fmt.Scanln(&score)
sum += score
}
fmt.Printf("第%d个班级的平均分为: %v n", j, sum / float64(stuNum))
total_sum += sum
}
fmt.Printf("所有班级的平均分为: %v n", total_sum / float64(stuNum * classNum))
}
输出结果为:
2) 案例2 打印金字塔
编写一个程序,接收一个整数表示层数,打印出金字塔。
package main
import (
"fmt"
)
func main() {
// 打印金字塔
/****************
*
***
*****
*****************/
var totalLevel int = 3
// i 表示层数
for i := 1; i <= totalLevel; i++ {
// k 表示每层打印多少空格
for k := 1; k <= totalLevel - i; k++ {
fmt.Print(" ")
}
// j 表示每层打印多少 *
for j := 1; j <= (2 * i - 1); j++ {
fmt.Print("*")
}
fmt.Println() // 换行
}
}
输出结果为:
打印空心金字塔。
package main
import (
"fmt"
)
func main() {
// 5. 打印空心金字塔
/****************
*
* *
*****
*****************/
var totalLevel int = 3
// i 表示层数
for i := 1; i <= totalLevel; i++ {
// k 表示每层打印多少空格
for k := 1; k <= totalLevel - i; k++ {
fmt.Print(" ")
}
// j 表示每层打印多少 *
if i != totalLevel{
for j := 1; j <= (2 * i - 1); j++ {
if j == 1 || j == (2 * i - 1) {
fmt.Print("*")
} else {
fmt.Print(" ")
}
}
} else {
for j := 1; j <= (2 * i - 1); j++ {
fmt.Print("*")
}
}
fmt.Println() // 换行
}
}
输出结果为:
五、跳转控制语句
1. break
break 用于终止某个语句块的执行,中断当前 for 循环或跳出 switch 语句。
随机生成1-100之间的整数,直到生成99时停止,记录生成了多少次。
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
// 生成随机种子
// time.Now().Unix():返回一个从1970/01/01 00:00:00 到现在的秒数
rand.Seed(time.Now().Unix())
// 随机生成1-100的整数
var n int
count := 0
for {
// rand.Seed(time.Now().UnixNano())
n = rand.Intn(100) + 1
count++
if n == 99 {
break
}
}
fmt.Println(n, count)
}
输出结果:
代码解释:
- 随机生成 0-100 之间的整数,调用 “math/rand” 包中的 Intn 函数;
- time 包中的 time.Now().Unix():返回一个从 1970/01/01 00:00:00 到现在的秒数。
使用细节
1、 break 语句出现在多层嵌套的语句块中,可通过标签(可以自定义名称)指明要终止的是哪一层语句块;
package main
import (
"fmt"
)
func main() {
var totalLevel int = 9
// i 表示层数
label1:
for i := 1; i <= totalLevel; i++ {
// j 表示每行的乘法算式
// label2
for j := 1; j <= i; j++ {
if j == 9 {
// break label2
break label1
}
fmt.Printf("%d * %d = %d t", i, j, i * j)
}
fmt.Println()
}
}
2. continue
continue 用于结束本次循环,直接跳转到循环变量迭代,继续执行下一次循环。同样地,continue语句出现在多层嵌套的语句块中,可通过标签(可以自定义名称)指明要跳过的是哪一层语句块。
3. goto (不主张使用)
goto 可以无条件转移到程序中指定的行。
// 基本语法
goto label
...
label: statement
最后
以上就是失眠大地为你收集整理的【Golang入门】九、程序流程控制的全部内容,希望文章能够帮你解决【Golang入门】九、程序流程控制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复