Go中的流程控制
分支控制
if 条件
基本语法:
在Go中if执行语句中即使只有一行代码也需要将其包含在大括号{}内,条件判断语句可以不使用小括号()括住,也可以使用小括号括住,建议不使用。
/*
if 条件判断语句1 {
// 执行语句
}else if 条件判断语句2{
// 执行语句
}else{
// 执行语句
}
*/
package main
import "fmt"
func main() {
var age int
fmt.Println("请输入年龄")
fmt.Scanln(&age)
if age > 10 {
fmt.Println("你不需要家长陪同就可以观看")
} else { // 需要使用大括号包含
fmt.Println("请在家长陪同下观看")
}
}
注意事项:
- Go语言中,条件判断语句里面允许声明变量(:=),这个变量的作用域在该条件逻辑块内,但是不能有赋值语句(=)
有啥使用场景??
if age := 9; age > 10 {
fmt.Println("你不需要家长陪同就可以观看")
} else {
fmt.Println("请在家长陪同下观看")
}
else
前面不能换行,必须紧跟if
的大括号,否则编译不通过
demo:求解方程
package main
import (
"fmt"
"math"
)
func main() {
var a float64
var b float64
var c float64
fmt.Println("请输入整数a,b,c,并用空格分开:")
fmt.Scanf("%f %f %f", &a, &b, &c)
m := b*b - 4*a*c
if m > 0 {
fmt.Println("方程有2个解")
x1 := (-b + math.Sqrt(m)) / (2 * a)
x2 := (-b - math.Sqrt(m)) / (2 * a)
fmt.Println("x1和x2为:", x1, x2)
} else if m == 0 {
x1 := (-b + math.Sqrt(m)) / (2 * a)
fmt.Println("方程的解为:", x1)
fmt.Println("方程有1个解")
} else {
fmt.Println("方程无解")
}
}
Switch语句
- Switch语句用于基于不同条件执行不同动作,每个case分支都是唯一的,从上往下逐级匹配
- Go语言中,case中不需要加break,默认会给加上
python3.10之前没有switch语句,3.10后加入了switch语句
- switch中的
case
后面可以写多个表达式,使用逗号隔开,运行时会逐一匹配
基于语法:
switch 表达式 {
case 表达式1,表达式2,...:
//语句块
case 表达式3,表达式4,...:
//语句块
default :
//语句块
}
package main
import "fmt"
func main() {
var key byte
fmt.Scanf("%c", &key)
switch key {
case 'a', '1':
fmt.Printf("输入的值为:%c", key)
fmt.Println("Monday")
case 'b', '2':
fmt.Printf("输入的值为:%c", key)
fmt.Println("Tuesday")
default:
fmt.Println("输入的值错误")
}
}
注意事项:
switch
和case
后是一个表达式(常量、变量、一个有返回值的函数等)case
后的各个表达式的值的数据类型必须要和switch
中表达式的值类型相同case
后面的表达式如果是常量值(字面量),则不能重复- 允许
switch
后面表达式为空,case
后面使用条件表达式,语法类似于if
条件表达式 - switch后可以直接声明或者定义变量,分号结束
switch
的穿透:case
中写入fallthrought
关键字,则执行完该case
之后会继续匹配其他case
中的表达式。效果类似于在一个case后面写入多个表达式- Type Switch:
for循环控制
基本语法:
/*
for 循环变量初始化;循环条件;循环变量迭代{
语句
}
*/
// i:=1 等价于 var i int = 1,这里使用:=和类型推导。
for i := 1;i<=10 ;i++{
// 循环操作
}
注意事项:
for
循环的第二种写法
/*
// 循环变量初始化
for 循环条件{
// 循环操作
// 循环变量迭代
}
*/
j := 1
for j<= 10{
//循环操作
j++
}
- 无限循环
/*
for{
// 循环语句
}
// 死循环,通常需要break
// 等价于for ;;{}
*/
for{
if 判断表达式 {
break
}else{
break
}
}
- Go提供for-range的方式来遍历字符串和数组
package main
import "fmt"
func main() {
var str string = "hello,world"
for i := 0; i < len(str); i++ {
fmt.Printf("%c\n", str[i])
}
// 通过 for range遍历字符串str,返回值为索引和值
for index, val := range str {
fmt.Printf("%d,%c\n", index, val)
}
}
注意事项:
- 如果字符串中含有中文,使用第一种方法(传统
for
循环)默认输出是以字节输出,而一个中文需要三个字节存储,所以会输出乱码。如果需要遍历输出中文字符串,需要先把字符串转化成[]rune
切片。 - 通过
for-range
方式可以不需要转换就可以输出带有中文的字符串,for-range
方式默认按照字符的方式遍历,但是索引会以步长为3
的大小变化(中文占3
个字节)
package main
import "fmt"
func main() {
var str string = "hello,北京"
for i := 0; i < len(str); i++ {
fmt.Printf("%c\n", str[i])
}
for index, val := range str {
fmt.Printf("%d,%c\n", index, val)
}
}
3. Go语言没有while
和do while
循环,可以通过for循环中的无限循环来实现
package main
import "fmt"
func main() {
var passwd int64
var userName string
var residueNum int = 3
for {
fmt.Println("请输入用户名和密码:")
fmt.Scanln(&userName)
fmt.Scanln(&passwd)
//fmt.Scanf("%s,%d", &userName, &passwd)
if userName == "admin" && passwd == 123456 {
fmt.Println("登录成功")
break
} else if residueNum <= 1 {
fmt.Println("密码错误次数太多,账号已被锁定,请联系管理员解锁") // 假装锁定了
break
} else {
residueNum -= 1
fmt.Printf("登录失败,还剩 %d 次机会", residueNum)
}
}
}
Go中的break的特殊性质
-
break语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块
- 标签语法
/* label1: for{ label2: // 如果label2没有用上,就不写(Go中用不上的变量都需要删除,否则编译不通过) for{ break label1 // 直接终止第一层循环 } } */ package main import ( "fmt" "math/rand" time2 "time" ) func main() { time := time2.Now().Unix() // 生成时间戳 fmt.Println("当前时间戳为:", time) rand.Seed(time) // 设置种子 randNum := rand.Intn(100) // 生成随机数 fmt.Println("随机数为:", randNum) label1: // 设置标签 for i := 0; i < 4; i++ { for j := 0; j <= 10; j++ { if j == 2 { break label1 // 直接终止第一层循环 } fmt.Println("j=", j) } } } /* output: 当前时间戳为: 1681560032 随机数为: 39 j= 0 j= 1 */
Go语言中continue的特殊性质
- 在多层循环嵌套中,
continue
语句可以通过标签指明要跳过哪一层循环,语法规则和break
类似
goto
Go语言中支持
goto
语句。基于语法
/* // 代码块0 goto label1 // 跳过代码块1 直接执行代码块2 // 代码块1 lebel1: // 代码块2 */