【Go】P6 Golang 基础:流程控制
目录
- 前言
- if-else 分支结构
- 基本语法
- 语法特点
- 示例代码
- 基础条件判断
- if 的特殊用法 - 在条件表达式前声明变量
- 多条件判断
- for 循环结构
- 基本语法
- 示例代码
- 标准 for 循环
- 类似 while 的用法
- 无限循环配合 break
- for 循环嵌套
- for range 键值循环
- 遍历切片
- 遍历字符串
- 遍历 map
- switch case 多分支结构
- 基本语法
- 示例代码
- 基础用法
- 一个分支多个值
- 省略 switch 后的变量 - 分支使用表达式
- switch 初始化语句
- fallthrough 穿透
- Continue、Break 与 Goto
- continue 继续下一次循环
- 示例代码
- break 跳出循环
- 示例代码
- goto 无条件跳转
- 基本语法
- 示例代码
- 使用注意事项
- 总结
前言
流程控制是每种编程语言控制逻辑走向和执行次序的重要部分,可以说是一门语言的"经脉"。Go 语言中最常用的流程控制有 if
和 for
,而 switch
和 goto
主要是为了简化代码、降低重复代码而生的结构,属于扩展类的流程控制。
if-else 分支结构
基本语法
if-else
是最基础的条件判断语句,用于根据条件执行不同的代码分支。其基本结构如下:
if 条件表达式 {// 条件为 true 时执行
} else if 条件表达式 {// 第一个条件为 false,此条件为 true 时执行
} else {// 所有条件都为 false 时执行
}
语法特点
Go 语言的 if
语句有以下几个重要特点:
- 可以省略条件表达式的小括号,这使代码更简洁
- 花括号
{}
不可省略,即使只有一行代码 - 左花括号
{
必须与if
在同一行,不能换行
示例代码
基础条件判断
age := 18if age >= 18 {fmt.Println("已成年")
} else {fmt.Println("未成年")
}
if 的特殊用法 - 在条件表达式前声明变量
在某些特殊场景下,可以将变量的声明放置在条件表达式前。
// 变量 score 的作用域仅限于 if-else 块内
if score := 85; score >= 90 {fmt.Println("优秀")
} else if score >= 60 {fmt.Println("及格")
} else {fmt.Println("不及格")
}
// 这里无法访问 score 变量
这种写法的优势是可以限制变量的作用域,避免变量污染外部作用域。
多条件判断
username := "admin"
password := "123456"if username == "admin" && password == "123456" {fmt.Println("登录成功")
} else if username != "admin" {fmt.Println("用户名错误")
} else {fmt.Println("密码错误")
}
for 循环结构
Go 语言中的所有循环类型均可以使用 for
关键字来完成,这是 Go 与其他语言的一个显著区别 - Go 中没有 while 和 do-while 语句。
基本语法
for 循环有多种形式:
// 完整形式
for 初始语句; 条件表达式; 结束语句 {// 循环体
}// 类似 while 的形式
for 条件表达式 {// 循环体
}// 无限循环
for {// 循环体
}
示例代码
标准 for 循环
// 打印 1 到 10
for i := 1; i <= 10; i++ {fmt.Println(i)
}
类似 while 的用法
i := 1
for i <= 10 {fmt.Println(i)i++
}
无限循环配合 break
count := 0
for {count++fmt.Println("循环次数:", count)if count >= 5 {break // 跳出循环}
}
for 循环嵌套
// 打印九九乘法表
for i := 1; i <= 9; i++ {for j := 1; j <= i; j++ {fmt.Printf("%d×%d=%d\t", j, i, i*j)}fmt.Println()
}
for range 键值循环
for range
是 Go 语言特有的迭代结构,可用于遍历数组、切片、字符串、map 和 channel。
遍历切片
nums := []int{10, 20, 30, 40, 50}// 同时获取索引和值
for index, value := range nums {fmt.Printf("索引: %d, 值: %d\n", index, value)
}// 只要值,忽略索引
for _, value := range nums {fmt.Println(value)
}// 只要索引
for index := range nums {fmt.Println(index)
}
遍历字符串
str := "Hello,世界"// range 遍历字符串时,value 是 rune 类型(Unicode 码点)
for index, char := range str {fmt.Printf("索引: %d, 字符: %c\n", index, char)
}
遍历 map
userMap := map[string]int{"Alice": 25,"Bob": 30,"Carol": 28,
}for key, value := range userMap {fmt.Printf("%s: %d岁\n", key, value)
}
switch case 多分支结构
switch
语句用于基于不同条件执行不同动作,是一种更优雅的多分支选择结构,可以替代冗长的 if-else
链。
基本语法
switch 变量 {
case 值1:// 执行代码块1
case 值2:// 执行代码块2
default:// 所有 case 都不匹配时执行
}
示例代码
基础用法
day := 3switch day {
case 1:fmt.Println("星期一")
case 2:fmt.Println("星期二")
case 3:fmt.Println("星期三")
case 4:fmt.Println("星期四")
case 5:fmt.Println("星期五")
case 6, 7: // 一个 case 可以有多个值fmt.Println("周末")
default:fmt.Println("无效的日期")
}
一个分支多个值
score := 'B'switch score {
case 'A', 'a':fmt.Println("优秀")
case 'B', 'b':fmt.Println("良好")
case 'C', 'c':fmt.Println("及格")
default:fmt.Println("不及格")
}
省略 switch 后的变量 - 分支使用表达式
age := 25switch {
case age < 18:fmt.Println("未成年")
case age >= 18 && age < 60:fmt.Println("成年人")
case age >= 60:fmt.Println("老年人")
}
这种方式类似于 if-else
链,但更加清晰。
switch 初始化语句
switch num := 10; {
case num > 0:fmt.Println("正数")
case num < 0:fmt.Println("负数")
default:fmt.Println("零")
}
fallthrough 穿透
Go 的 switch
默认每个 case
执行完后会自动跳出(不需要 break),如果需要继续执行下一个 case
,需要使用 fallthrough
关键字。
num := 1switch num {
case 1:fmt.Println("case 1")fallthrough // 强制穿透到下一个 case
case 2:fmt.Println("case 2")fallthrough
case 3:fmt.Println("case 3")
default:fmt.Println("default")
}// 输出:
// case 1
// case 2
// case 3
注意事项:
- Go 的
switch
默认不穿透,执行完匹配的case
后自动结束 fallthrough
会无条件执行下一个case
,不判断条件fallthrough
不能用在switch
的最后一个case
中- 虽然不需要
break
,但建议标注出明晰整体逻辑
Continue、Break 与 Goto
continue 继续下一次循环
continue
语句用于跳过当前循环的剩余代码,直接开始下一次循环迭代。continue
只能在 for
循环中使用。
示例代码
跳过偶数:
for i := 1; i <= 10; i++ {if i%2 == 0 {continue // 跳过偶数,不打印}fmt.Println(i)
}
// 输出: 1 3 5 7 9
continue 配合标签用于嵌套循环:
OuterLoop:
for i := 1; i <= 3; i++ {for j := 1; j <= 3; j++ {if j == 2 {continue OuterLoop // 跳过外层循环的当前迭代}fmt.Printf("i=%d, j=%d\n", i, j)}
}
break 跳出循环
break
语句用于立即终止循环或 switch
语句的执行,程序会跳转到循环或 switch
之后的代码。
示例代码
跳出单层循环:
for i := 1; i <= 10; i++ {if i == 5 {break // 当 i 等于 5 时跳出循环}fmt.Println(i)
}
// 输出: 1 2 3 4
在 switch 中使用 break
score := 85switch {
case score >= 90:fmt.Println("优秀")
case score >= 60:fmt.Println("及格")if score < 70 {fmt.Println("需要继续努力")break // 提前退出 switch}fmt.Println("表现不错")
default:fmt.Println("不及格")
}
break 结合标签跳出多层循环
在嵌套循环中,普通的 break
只能跳出当前层循环。如果需要跳出外层循环,可以使用标签。
OuterLoop:
for i := 1; i <= 3; i++ {for j := 1; j <= 3; j++ {fmt.Printf("i=%d, j=%d\n", i, j)if i == 2 && j == 2 {break OuterLoop // 直接跳出外层循环}}
}
fmt.Println("循环结束")// 输出:
// i=1, j=1
// i=1, j=2
// i=1, j=3
// i=2, j=1
// i=2, j=2
// 循环结束
goto 无条件跳转
goto
语句可以无条件地跳转到程序中指定的标签位置。虽然 goto
可以简化某些场景的代码,但过度使用会使程序逻辑混乱,降低可读性。因此应谨慎使用。
基本语法
goto 标签名标签名:// 从这里继续执行
示例代码
简单跳转:
fmt.Println("开始")
goto End
fmt.Println("这行不会执行")End:fmt.Println("跳转到这里")fmt.Println("程序结束")// 输出:
// 开始
// 跳转到这里
// 程序结束
跳出多层循环:
for i := 0; i < 5; i++ {for j := 0; j < 5; j++ {if i*j > 6 {goto BreakAll // 跳出所有循环}fmt.Printf("i=%d, j=%d, i*j=%d\n", i, j, i*j)}
}BreakAll:fmt.Println("已跳出所有循环")
错误处理场景:
func processFile() error {file, err := openFile()if err != nil {goto CleanUp}data, err := readFile(file)if err != nil {goto CleanUp}err = processData(data)if err != nil {goto CleanUp}return nilCleanUp:closeFile(file)return err
}
使用注意事项
goto
不能跳转到其他函数内部goto
不能跳过变量声明语句- 应优先考虑使用其他控制结构(如
break
、continue
)代替goto
- 合理的使用场景:统一的错误处理、跳出深层嵌套循环
总结
Go 语言的流程控制简洁而强大:
- if-else: 条件分支的基础,支持在条件中声明变量
- for: 唯一的循环关键字,涵盖所有循环场景,包括传统循环、类 while 循环和
for range
迭代 - switch:优雅的多分支选择,默认不穿透,支持多值匹配和表达式判断
- break/continue:控制循环执行流程,支持标签跳转
- goto:无条件跳转,应谨慎使用
掌握这些流程控制语句,能够帮助你编写出结构清晰、逻辑严谨的 Go 程序。在实际开发中,建议优先使用 if
、for
和 switch
,只在必要时才使用 goto
,以保持代码的可读性和可维护性。
2025.10.15 西直门