Go 并发编程 - 第 4 课:if/else 与循环
1. 学习目标
通过本课学习,你将能够:
- 掌握条件判断:熟练使用
if/else语句处理程序中的分支逻辑 - 精通循环控制:理解
for循环的多种用法,包括计数循环、条件循环和无限循环 - 灵活运用 switch:使用
switch语句简化多条件判断,理解fallthrough关键字 - 掌握 range 遍历:使用
range关键字高效遍历数组、切片、字符串、映射等数据结构 - 避免常见陷阱:识别并避免初学者在条件判断和循环中常犯的错误
2. 核心概念
2.1 if/else 条件判断
if/else 是程序中最基本的控制结构,用于根据条件执行不同的代码块。
基本语法:
if condition {
// 条件为真时执行
} else if anotherCondition {
// 另一个条件为真时执行
} else {
// 所有条件都不满足时执行
}
特点:
- 条件表达式不需要用括号包裹
- 大括号
{}是必须的,即使只有一行代码 - 可以包含多个
else if分支 - 支持在 if 前声明变量(仅在 if 作用域内有效)
2.2 for 循环
Go 语言中只有 for 一种循环结构,但功能非常强大。
三种基本形式:
// 1. 传统的三段式循环
for i := 0; i < 10; i++ {
// 计数循环
}
// 2. 条件循环(类似 while)
for condition {
// 条件为真时继续循环
}
// 3. 无限循环
for {
// 永远循环,需要 break 退出
}
2.3 switch 语句
switch 语句用于多分支选择,比多个 if-else 更清晰。
特点:
- 每个 case 自动 break,不会"穿透"到下一个 case
- 可以使用
fallthrough强制执行下一个 case - case 可以是多个值(用逗号分隔)
- 支持无条件的 switch(替代长 if-else 链)
2.4 range 关键字
range 用于遍历各种数据结构,是 Go 中处理集合的常用方式。
可遍历的类型:
- 数组和切片:返回索引和值
- 字符串:返回索引和 Unicode 码点
- 映射:返回键和值
- 通道:返回接收到的值(并发编程中重要)
3. 代码示例
3.1 if/else 示例
package main
import "fmt"
func main() {
// 基本的 if/else
temperature := 25
if temperature > 30 {
fmt.Println("天气很热,开空调!")
} else if temperature > 20 {
fmt.Println("天气不错,适合户外活动")
} else {
fmt.Println("有点冷,多穿点衣服")
}
// 带初始化语句的 if
if hour := 14; hour < 12 {
fmt.Println("现在是上午")
} else {
fmt.Println("现在是下午")
}
}
3.2 for 循环示例
package main
import "fmt"
func main() {
// 计数循环
fmt.Println("1. 计数循环:")
for i := 1; i <= 5; i++ {
fmt.Printf("%d ", i)
}
fmt.Println()
// 条件循环(类似 while)
fmt.Println("2. 条件循环:")
count := 0
for count < 3 {
fmt.Printf("循环第 %d 次\n", count+1)
count++
}
// 无限循环与 break
fmt.Println("3. 无限循环:")
i := 0
for {
if i >= 3 {
break // 跳出循环
}
fmt.Printf("无限循环第 %d 次\n", i+1)
i++
}
// 使用 continue 跳过本次循环
fmt.Println("4. 使用 continue:")
for i := 0; i < 5; i++ {
if i == 2 {
continue // 跳过本次循环
}
fmt.Printf("%d ", i)
}
fmt.Println()
}
3.3 switch 语句示例
package main
import "fmt"
func main() {
// 基本的 switch
day := "Wednesday"
switch day {
case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday":
fmt.Println("今天是工作日")
case "Saturday", "Sunday":
fmt.Println("今天是周末")
default:
fmt.Println("无效的日期")
}
// 无表达式的 switch(替代 if-else 链)
score := 85
switch {
case score >= 90:
fmt.Println("优秀")
case score >= 80:
fmt.Println("良好")
case score >= 70:
fmt.Println("中等")
case score >= 60:
fmt.Println("及格")
default:
fmt.Println("不及格")
}
// fallthrough 示例
num := 1
switch num {
case 1:
fmt.Println("匹配 case 1")
fallthrough // 继续执行下一个 case
case 2:
fmt.Println("匹配 case 2 或 fallthrough 到这里")
case 3:
fmt.Println("匹配 case 3")
}
}
3.4 range 遍历示例
package main
import "fmt"
func main() {
// 遍历数组
colors := [3]string{"Red", "Green", "Blue"}
fmt.Println("遍历数组:")
for index, color := range colors {
fmt.Printf("索引: %d, 值: %s\n", index, color)
}
// 遍历切片
nums := []int{10, 20, 30, 40, 50}
fmt.Println("\n遍历切片:")
for i, v := range nums {
fmt.Printf("nums[%d] = %d\n", i, v)
}
// 遍历字符串
str := "Go语言"
fmt.Println("\n遍历字符串:")
for i, c := range str {
fmt.Printf("索引: %d, Unicode: %U, 字符: %c\n", i, c, c)
}
// 遍历映射
studentScores := map[string]int{
"Alice": 90,
"Bob": 85,
"Carol": 92,
}
fmt.Println("\n遍历映射:")
for name, score := range studentScores {
fmt.Printf("%s 的成绩是 %d 分\n", name, score)
}
// 忽略索引或值
fmt.Println("\n只获取值:")
for _, v := range nums {
fmt.Printf("%d ", v)
}
fmt.Println()
}
4. 实践练习
练习 1:成绩等级判断(简单)
编写程序,输入一个 0-100 之间的成绩分数,输出对应的等级:
- 90-100: A
- 80-89: B
- 70-79: C
- 60-69: D
- 0-59: F
// 预期输出示例:
// 输入: 85
// 输出: 等级为: B
// 输入: 92
// 输出: 等级为: A
练习 2:九九乘法表(中等)
使用 for 循环打印完整的九九乘法表。
// 预期输出:
// 1*1=1
// 1*2=2 2*2=4
// 1*3=3 2*3=6 3*3=9
// ...
练习 3:统计字符频率(较难)
编写程序,输入一个字符串,使用 for range 遍历并统计每个字符出现的次数,然后输出出现频率最高的字符及其出现次数。
// 预期输出示例:
// 输入: "hello world"
// 输出: 字符 'l' 出现了 3 次
5. 常见错误
5.1 if 语句的常见错误
// 错误 1:条件表达式忘记括号(Go 中不需要括号)
// 错误写法:
if (x > 10) {
// ...
}
// 正确写法:
if x > 10 {
// ...
}
// 错误 2:赋值符号误用为比较符号
x := 5
// 错误写法:这会将 10 赋值给 x,而不是比较
if x = 10 {
// 这行代码会报错,因为 x = 10 返回的是 10(bool 类型)
}
// 正确写法:
if x == 10 {
// ...
}
5.2 for 循环的常见错误
// 错误 1:循环变量作用域问题
for i := 0; i < 10; i++ {
// 这里的 i 在循环结束后就不能访问了
}
// fmt.Println(i) // 错误:i 未定义
// 错误 2:无限循环忘记退出条件
count := 0
for count < 10 {
// 忘记增加 count,导致无限循环
// count++ 忘记写了!
fmt.Println(count)
}
5.3 switch 语句的常见错误
// 错误 1:误以为需要 break(Go 中每个 case 自动 break)
switch num {
case 1:
fmt.Println("一")
break // 这行是多余的,但不会出错
case 2:
fmt.Println("二")
}
// 错误 2:误用 fallthrough
switch num {
case 1:
fmt.Println("一")
fallthrough // 即使下一个 case 不匹配也会执行
case 2:
fmt.Println("二") // 当 num=1 时,这里也会执行
}
5.4 range 遍历的常见错误
// 错误:忽略 range 的返回值
// 错误写法:
for range nums {
// 只知道遍历了多少次,不知道具体值
}
// 正确写法:
for i, v := range nums {
fmt.Printf("索引 %d, 值 %d\n", i, v)
}
// 错误:在遍历中修改映射可能导致问题
m := map[string]int{"a": 1, "b": 2}
for k, v := range m {
if v == 1 {
delete(m, k) // 在遍历中删除元素是安全的
}
}
6. 小结
本课学习了 Go 语言中最基本的控制结构:
关键要点:
-
if/else 条件判断
- 使用
if处理条件分支 - 支持
else if和else - 可以在 if 前声明变量(限定作用域)
- 使用
-
for 循环
- Go 中唯一的循环结构
- 三种形式:计数循环、条件循环、无限循环
- 使用
break退出循环,continue跳过当前迭代
-
switch 语句
- 多分支选择,比多个 if-else 更清晰
- 每个 case 自动 break
- 支持无条件的 switch(替代 if-else 链)
- 使用
fallthrough继续执行下一个 case
-
range 遍历
- 遍历数组、切片、字符串、映射等
- 返回索引和值(可使用
_忽略不需要的) - 是处理集合数据的首选方式
最佳实践:
- 保持条件判断清晰简洁
- 避免过深的嵌套(超过 3 层考虑重构)
- 优先使用
switch替代长if-else链 - 使用
range遍历集合,代码更简洁安全 - 注意循环中的边界条件,避免死循环或越界
掌握了这些控制结构,你就能编写出逻辑清晰、结构良好的 Go 程序了。下一课我们将学习数组与切片,继续探索 Go 语言的数据结构。
练习编辑器
go
Loading...