Golang入门:分支与循环:控制程序流程
在任何编程语言中,控制程序的执行流程都是最核心的概念之一。它决定了代码在何种条件下执行哪部分逻辑,以及如何重复执行特定任务。Go语言以其简洁明了的语法设计,提供了强大而清晰的分支和循环结构。本文将带你深入浅出地掌握Go语言中的if
, switch
, for
等关键字,让你能精准地控制程序的走向。
一、条件分支(if/else)
条件分支语句用于根据一个或多个条件的真假来决定执行哪一段代码。Go语言中的if
语句写法既直观又灵活。
基本语法
最基本的if
语句语法如下:
if condition {
// 条件为 true 时执行的代码
}
你还可以加入else
和else if
来处理其他情况:
score := 85
if score >= 90 {
fmt.Println("优秀")
} else if score >= 80 {
fmt.Println("良好")
} else if score >= 60 {
fmt.Println("及格")
} else {
fmt.Println("不及格")
}
// 输出:良好
特殊语法:在条件前执行一个语句
Go的if
语句还有一个非常实用的特性:允许在条件判断之前执行一个简单的语句,通常用于变量的初始化,该变量的作用域被限制在if
语句块内。
// 从函数获取一个值并立即判断
if num := getNumber(); num < 0 {
fmt.Println("数字是负数:", num)
} else {
fmt.Println("数字是正数或零:", num)
}
// 注意:此处无法再访问变量 num
这种写法让代码更加紧凑,避免了在外部声明一个可能只用于一次判断的变量。
二、多路选择(switch)
当你的条件分支变得非常多时,使用一连串的else if
会显得冗长且难以维护。这时,switch
语句就是更好的选择。Go中的switch
比其他语言中的更加强大和灵活。
基本用法
最常见的用法是基于一个变量的值进行分支选择。
day := "Tuesday"
switch day {
case "Monday":
fmt.Println("周一,上班啦!")
case "Tuesday":
fmt.Println("周二,继续努力!")
case "Wednesday", "Thursday": // 一个case可以匹配多个表达式
fmt.Println("周中,坚持住!")
case "Friday":
fmt.Println("周五,胜利在望!")
default: // 可选的,匹配所有其他情况
fmt.Println("周末,休息!")
}
// 输出:周二,继续努力!
无表达式的switch(True Switch)
你可以省略switch
后面的表达式,这时每个case
条件都是一个独立的布尔表达式。这相当于一个写得更清晰的if-else if
链。
score := 88
switch {
case score >= 90:
fmt.Println("A")
case score >= 80:
fmt.Println("B")
case score >= 70:
fmt.Println("C")
default:
fmt.Println("D")
}
// 输出:B
fallthrough关键字
在Go中,switch
的case
分支默认会自动终止(即不会继续执行下一个case
)。如果你需要C语言中那种不加break
就会继续执行后续case的行为,可以使用fallthrough
关键字。
num := 1
switch num {
case 1:
fmt.Println("数字是 1")
fallthrough // 继续执行下一个case
case 2:
fmt.Println("数字是 2")
default:
fmt.Println("其他数字")
}
// 输出:
// 数字是 1
// 数字是 2
需要注意的是,fallthrough
不会判断下一个case
的条件是否为true
,它会无条件地执行下一个case
的代码。
三、循环(for)
Go语言中只有一个循环结构——for
循环。但它通过不同的写法可以实现其他语言中for
, while
, do-while
循环的所有功能,语法非常统一。
经典for循环
最经典的三段式写法,适用于你知道循环次数的情况。
// 打印 0 到 4
for i := 0; i < 5; i++ {
fmt.Println(i)
}
类似while的循环
省略初始化和步进语句,只保留条件语句,for
循环就变成了while
循环。
// 模拟 while (count < 5)
count := 0
for count < 5 {
fmt.Println(count)
count++
}
无限循环
如果连条件语句也省略,那么就创建了一个无限循环,通常需要配合break
语句在内部退出。
// 无限循环,直到遇到 break
num := 0
for {
if num >= 5 {
break // 跳出循环
}
fmt.Println(num)
num++
}
for-range 循环
遍历数组(Array)、切片(Slice)、字符串(String)、映射(Map)或通道(Channel)时,for-range
循环是最高效和方便的方式。
// 遍历切片
fruits := []string{"Apple", "Banana", "Orange"}
for index, value := range fruits {
fmt.Printf("索引: %d, 值: %s\n", index, value)
}
// 如果你不需要索引,可以用下划线 _ 忽略它
for _, fruit := range fruits {
fmt.Println(fruit)
}
// 遍历字符串(得到的是rune,而不是byte)
for i, r := range "Hello, 世界" {
fmt.Printf("位置 %d: %c\n", i, r)
}
// 遍历Map
kvs := map[string]string{"a": "apple", "b": "banana"}
for k, v := range kvs {
fmt.Printf("%s -> %s\n", k, v)
}
四、循环控制语句(break, continue, goto)
在循环内部,你可以使用控制语句来更精细地管理循环的流程。
- break:立即终止当前最内层的循环,并开始执行循环之后的语句。
- continue:跳过当前循环迭代中剩余的语句,直接开始下一次迭代。
- goto:无条件地跳转到函数内指定的标签(Label)处。慎用,因为它容易导致代码流程混乱。
// break 示例:找到一个数字就退出
for i := 0; i < 10; i++ {
if i == 5 {
fmt.Println("找到5了!")
break
}
}
// continue 示例:只打印奇数
for i := 0; i < 10; i++ {
if i%2 == 0 {
continue // 如果是偶数,跳过打印
}
fmt.Println("奇数:", i)
}
五、实战应用场景
场景1:用户输入验证
// 模拟验证用户输入不能为空
var input string
for {
fmt.Print("请输入您的姓名: ")
fmt.Scanln(&input)
if strings.TrimSpace(input) != "" {
break // 输入有效,退出循环
}
fmt.Println("输入不能为空,请重新输入!")
}
fmt.Printf("你好,%s!\n", input)
场景2:处理集合数据
// 统计一个切片中正数的个数
numbers := []int{-2, 5, 0, 12, -8, 7}
positiveCount := 0
for _, num := range numbers {
if num <= 0 {
continue // 遇到非正数,跳过后续计数代码
}
positiveCount++
// 其他处理正数的逻辑...
}
fmt.Printf("正数的个数是: %d\n", positiveCount)
场景3:模拟简单状态机
// 使用switch根据当前状态执行不同操作
currentState := "开始"
for i := 0; i < 3; i++ {
switch currentState {
case "开始":
fmt.Println("系统启动中...")
currentState = "运行中"
case "运行中":
fmt.Println("系统正在处理任务...")
currentState = "结束"
case "结束":
fmt.Println("系统正在关闭...")
}
}
总结
Go语言通过if
, switch
, for
这三个核心关键字,提供了所有必要的程序流程控制能力。其设计哲学是简洁与实用:
if
语句支持在条件前执行简单语句,缩小了变量作用域。switch
语句功能强大,无需