【Go】P6 Golang 基础:流程控制

目录

前言

流程控制是每种编程语言控制逻辑走向执行次序 的重要部分,可以说是一门语言的"经脉"。Go 语言中最常用的流程控制有 iffor,而 switchgoto 主要是为了简化代码、降低重复代码而生的结构,属于扩展类的流程控制。


if-else 分支结构

基本语法

if-else 是最基础的条件判断语句,用于根据条件执行不同的代码分支。其基本结构如下:

go 复制代码
if 条件表达式 {
    // 条件为 true 时执行
} else if 条件表达式 {
    // 第一个条件为 false,此条件为 true 时执行
} else {
    // 所有条件都为 false 时执行
}

语法特点

Go 语言的 if 语句有以下几个重要特点:

  • 可以省略条件表达式的小括号,这使代码更简洁
  • 花括号 {} 不可省略,即使只有一行代码
  • 左花括号 { 必须与 if 在同一行,不能换行

示例代码

基础条件判断

go 复制代码
age := 18

if age >= 18 {
    fmt.Println("已成年")
} else {
    fmt.Println("未成年")
}

if 的特殊用法 - 在条件表达式前声明变量

在某些特殊场景下,可以将变量的声明放置在条件表达式前。

go 复制代码
// 变量 score 的作用域仅限于 if-else 块内
if score := 85; score >= 90 {
    fmt.Println("优秀")
} else if score >= 60 {
    fmt.Println("及格")
} else {
    fmt.Println("不及格")
}
// 这里无法访问 score 变量

这种写法的优势是可以限制变量的作用域,避免变量污染外部作用域。

多条件判断

go 复制代码
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 循环有多种形式:

go 复制代码
// 完整形式
for 初始语句; 条件表达式; 结束语句 {
    // 循环体
}

// 类似 while 的形式
for 条件表达式 {
    // 循环体
}

// 无限循环
for {
    // 循环体
}

示例代码

标准 for 循环

go 复制代码
// 打印 1 到 10
for i := 1; i <= 10; i++ {
    fmt.Println(i)
}

类似 while 的用法

go 复制代码
i := 1
for i <= 10 {
    fmt.Println(i)
    i++
}

无限循环配合 break

go 复制代码
count := 0
for {
    count++
    fmt.Println("循环次数:", count)
    
    if count >= 5 {
        break // 跳出循环
    }
}

for 循环嵌套

go 复制代码
// 打印九九乘法表
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。

遍历切片

go 复制代码
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)
}

遍历字符串

go 复制代码
str := "Hello,世界"

// range 遍历字符串时,value 是 rune 类型(Unicode 码点)
for index, char := range str {
    fmt.Printf("索引: %d, 字符: %c\n", index, char)
}

遍历 map

go 复制代码
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 链。

基本语法

go 复制代码
switch 变量 {
case 值1:
    // 执行代码块1
case 值2:
    // 执行代码块2
default:
    // 所有 case 都不匹配时执行
}

示例代码

基础用法

go 复制代码
day := 3

switch 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("无效的日期")
}

一个分支多个值

go 复制代码
score := 'B'

switch score {
case 'A', 'a':
    fmt.Println("优秀")
case 'B', 'b':
    fmt.Println("良好")
case 'C', 'c':
    fmt.Println("及格")
default:
    fmt.Println("不及格")
}

省略 switch 后的变量 - 分支使用表达式

go 复制代码
age := 25

switch {
case age < 18:
    fmt.Println("未成年")
case age >= 18 && age < 60:
    fmt.Println("成年人")
case age >= 60:
    fmt.Println("老年人")
}

这种方式类似于 if-else 链,但更加清晰。

switch 初始化语句

go 复制代码
switch num := 10; {
case num > 0:
    fmt.Println("正数")
case num < 0:
    fmt.Println("负数")
default:
    fmt.Println("零")
}

fallthrough 穿透

Go 的 switch 默认每个 case 执行完后会自动跳出(不需要 break) ,如果需要继续执行下一个 case,需要使用 fallthrough 关键字。

go 复制代码
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")
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 循环中使用。

示例代码

跳过偶数:

go 复制代码
for i := 1; i <= 10; i++ {
    if i%2 == 0 {
        continue  // 跳过偶数,不打印
    }
    fmt.Println(i)
}
// 输出: 1 3 5 7 9

continue 配合标签用于嵌套循环:

go 复制代码
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 之后的代码。

示例代码

跳出单层循环:

go 复制代码
for i := 1; i <= 10; i++ {
    if i == 5 {
        break  // 当 i 等于 5 时跳出循环
    }
    fmt.Println(i)
}
// 输出: 1 2 3 4

在 switch 中使用 break

go 复制代码
score := 85

switch {
case score >= 90:
    fmt.Println("优秀")
case score >= 60:
    fmt.Println("及格")
    if score < 70 {
        fmt.Println("需要继续努力")
        break  // 提前退出 switch
    }
    fmt.Println("表现不错")
default:
    fmt.Println("不及格")
}

break 结合标签跳出多层循环

在嵌套循环中,普通的 break 只能跳出当前层循环。如果需要跳出外层循环,可以使用标签。

go 复制代码
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 可以简化某些场景的代码,但过度使用会使程序逻辑混乱,降低可读性。因此应谨慎使用。

基本语法

go 复制代码
goto 标签名

标签名:
    // 从这里继续执行

示例代码

简单跳转:

go 复制代码
fmt.Println("开始")
goto End
fmt.Println("这行不会执行")

End:
    fmt.Println("跳转到这里")
    fmt.Println("程序结束")

// 输出:
// 开始
// 跳转到这里
// 程序结束

跳出多层循环:

go 复制代码
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("已跳出所有循环")

错误处理场景:

go 复制代码
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 nil

CleanUp:
    closeFile(file)
    return err
}

使用注意事项

  • goto 不能跳转到其他函数内部
  • goto 不能跳过变量声明语句
  • 应优先考虑使用其他控制结构(如 breakcontinue)代替 goto
  • 合理的使用场景:统一的错误处理、跳出深层嵌套循环

总结

Go 语言的流程控制简洁而强大:

  • if-else: 条件分支的基础,支持在条件中声明变量
  • for : 唯一的循环关键字,涵盖所有循环场景,包括传统循环、类 while 循环和 for range 迭代
  • switch:优雅的多分支选择,默认不穿透,支持多值匹配和表达式判断
  • break/continue:控制循环执行流程,支持标签跳转
  • goto:无条件跳转,应谨慎使用

掌握这些流程控制语句,能够帮助你编写出结构清晰、逻辑严谨的 Go 程序。在实际开发中,建议优先使用 ifforswitch,只在必要时才使用 goto,以保持代码的可读性和可维护性。


2025.10.15 西直门

相关推荐
信息快讯3 小时前
“COMSOL+MATLAB光子学仿真:从入门到精通,掌握多物理场建模
开发语言·matlab·comsol·光学工程
LK_073 小时前
【Open3D】Ch.3:顶点法向量估计 | Python
开发语言·笔记·python
小码哥0683 小时前
智能化招聘系统设计与实现-Java
开发语言·python
北山太湖3 小时前
Matlab安装硬件支持包
开发语言·matlab
QX_hao4 小时前
【Go】--数组和切片
后端·golang·restful
-睡到自然醒~4 小时前
提升应用性能:Go中的同步与异步处理
开发语言·后端·golang
只吃不吃香菜4 小时前
Go WebSocket 协程泄漏问题分析与解决方案
开发语言·websocket·golang
学Java的bb4 小时前
MybatisPlus
java·开发语言·数据库