Go学习笔记-Control Flow

Go语言的控制流语句包括条件语句、循环语句和跳转语句。Go的控制流语法简洁明了,没有while和do-while循环,只有for循环的多种形式。

if语句

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package main

import "fmt"

func main() {
    // 1. 基本if语句
    age := 18
    if age >= 18 {
        fmt.Println("你已经成年了")
    }
    
    // 2. if-else语句
    score := 85
    if score >= 90 {
        fmt.Println("优秀")
    } else if score >= 80 {
        fmt.Println("良好")
    } else if score >= 70 {
        fmt.Println("中等")
    } else if score >= 60 {
        fmt.Println("及格")
    } else {
        fmt.Println("不及格")
    }
    
    // 3. if语句的初始化
    if num := 42; num > 0 {
        fmt.Printf("num是正数: %d\n", num)
    } else if num < 0 {
        fmt.Printf("num是负数: %d\n", num)
    } else {
        fmt.Printf("num是零: %d\n", num)
    }
    // 注意:num变量只在if语句块内有效
    
    // 4. 复杂条件判断
    username := "admin"
    password := "123456"
    
    if len(username) > 0 && len(password) >= 6 {
        if username == "admin" && password == "123456" {
            fmt.Println("登录成功")
        } else {
            fmt.Println("用户名或密码错误")
        }
    } else {
        fmt.Println("用户名或密码格式不正确")
    }
    
    // 5. 检查错误的常见模式
    if err := doSomething(); err != nil {
        fmt.Printf("操作失败: %v\n", err)
        return
    }
    fmt.Println("操作成功")
    
    // 6. 类型断言与if语句
    var i interface{} = "hello"
    if str, ok := i.(string); ok {
        fmt.Printf("字符串值: %s\n", str)
    } else {
        fmt.Println("不是字符串类型")
    }
    
    // 7. 映射查找与if语句
    m := map[string]int{"apple": 5, "banana": 3}
    if value, exists := m["apple"]; exists {
        fmt.Printf("apple的值: %d\n", value)
    } else {
        fmt.Println("apple不存在")
    }
}

func doSomething() error {
    // 模拟可能出错的操作
    return nil  // 返回nil表示没有错误
}

switch语句

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package main

import (
    "fmt"
    "time"
)

func main() {
    // 1. 基本switch语句
    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("无效的日期")
    }
    
    // 2. switch语句的初始化
    switch hour := time.Now().Hour(); {
    case hour < 6:
        fmt.Println("凌晨")
    case hour < 12:
        fmt.Println("上午")
    case hour < 18:
        fmt.Println("下午")
    default:
        fmt.Println("晚上")
    }
    
    // 3. 无表达式的switch(相当于if-else链)
    score := 85
    switch {
    case score >= 90:
        fmt.Println("A级")
    case score >= 80:
        fmt.Println("B级")
    case score >= 70:
        fmt.Println("C级")
    case score >= 60:
        fmt.Println("D级")
    default:
        fmt.Println("F级")
    }
    
    // 4. fallthrough关键字
    grade := 'B'
    switch grade {
    case 'A':
        fmt.Println("优秀")
        fallthrough  // 继续执行下一个case
    case 'B':
        fmt.Println("良好")
        fallthrough
    case 'C':
        fmt.Println("及格")
    case 'D':
        fmt.Println("不及格")
    default:
        fmt.Println("无效等级")
    }
    
    // 5. 类型switch
    var x interface{} = 42
    switch v := x.(type) {
    case nil:
        fmt.Println("x是nil")
    case int:
        fmt.Printf("x是int类型,值为: %d\n", v)
    case string:
        fmt.Printf("x是string类型,值为: %s\n", v)
    case bool:
        fmt.Printf("x是bool类型,值为: %t\n", v)
    default:
        fmt.Printf("x是未知类型: %T\n", v)
    }
    
    // 6. 复杂的case表达式
    num := 15
    switch {
    case num%2 == 0 && num > 10:
        fmt.Println("大于10的偶数")
    case num%2 == 1 && num > 10:
        fmt.Println("大于10的奇数")
    case num%2 == 0:
        fmt.Println("小于等于10的偶数")
    default:
        fmt.Println("小于等于10的奇数")
    }
    
    // 7. 字符串switch
    operation := "add"
    a, b := 10, 5
    switch operation {
    case "add", "plus", "+":
        fmt.Printf("%d + %d = %d\n", a, b, a+b)
    case "sub", "minus", "-":
        fmt.Printf("%d - %d = %d\n", a, b, a-b)
    case "mul", "multiply", "*":
        fmt.Printf("%d * %d = %d\n", a, b, a*b)
    case "div", "divide", "/":
        if b != 0 {
            fmt.Printf("%d / %d = %d\n", a, b, a/b)
        } else {
            fmt.Println("除数不能为零")
        }
    default:
        fmt.Println("不支持的操作")
    }
}

for循环

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package main

import "fmt"

func main() {
    // 1. 传统的for循环
    fmt.Println("1. 传统for循环:")
    for i := 0; i < 5; i++ {
        fmt.Printf("i = %d\n", i)
    }
    
    // 2. 省略初始化的for循环
    fmt.Println("\n2. 省略初始化:")
    j := 0
    for ; j < 3; j++ {
        fmt.Printf("j = %d\n", j)
    }
    
    // 3. 省略后置语句的for循环
    fmt.Println("\n3. 省略后置语句:")
    k := 0
    for k < 3 {
        fmt.Printf("k = %d\n", k)
        k++
    }
    
    // 4. 无限循环
    fmt.Println("\n4. 无限循环(带break):")
    count := 0
    for {
        if count >= 3 {
            break
        }
        fmt.Printf("count = %d\n", count)
        count++
    }
    
    // 5. range循环 - 遍历数组/切片
    fmt.Println("\n5. range遍历切片:")
    numbers := []int{10, 20, 30, 40, 50}
    
    // 同时获取索引和值
    for index, value := range numbers {
        fmt.Printf("numbers[%d] = %d\n", index, value)
    }
    
    // 只获取索引
    fmt.Println("\n只获取索引:")
    for index := range numbers {
        fmt.Printf("索引: %d\n", index)
    }
    
    // 只获取值
    fmt.Println("\n只获取值:")
    for _, value := range numbers {
        fmt.Printf("值: %d\n", value)
    }
    
    // 6. range循环 - 遍历字符串
    fmt.Println("\n6. range遍历字符串:")
    str := "Hello, 世界"
    
    // 按字节遍历
    fmt.Println("按字节遍历:")
    for i := 0; i < len(str); i++ {
        fmt.Printf("str[%d] = %c (%d)\n", i, str[i], str[i])
    }
    
    // 按Unicode字符遍历
    fmt.Println("\n按Unicode字符遍历:")
    for index, char := range str {
        fmt.Printf("字符 '%c' 在索引 %d\n", char, index)
    }
    
    // 7. range循环 - 遍历映射
    fmt.Println("\n7. range遍历映射:")
    m := map[string]int{
        "apple":  5,
        "banana": 3,
        "orange": 8,
    }
    
    for key, value := range m {
        fmt.Printf("%s: %d\n", key, value)
    }
    
    // 只遍历键
    fmt.Println("\n只遍历键:")
    for key := range m {
        fmt.Printf("键: %s\n", key)
    }
    
    // 8. range循环 - 遍历通道
    fmt.Println("\n8. range遍历通道:")
    ch := make(chan int, 3)
    ch <- 1
    ch <- 2
    ch <- 3
    close(ch)  // 关闭通道
    
    for value := range ch {
        fmt.Printf("从通道接收: %d\n", value)
    }
    
    // 9. 嵌套循环
    fmt.Println("\n9. 嵌套循环:")
    for i := 1; i <= 3; i++ {
        for j := 1; j <= 3; j++ {
            fmt.Printf("(%d,%d) ", i, j)
        }
        fmt.Println()
    }
    
    // 10. 带标签的循环控制
    fmt.Println("\n10. 带标签的循环:")
outer:
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            if i == 1 && j == 1 {
                fmt.Println("跳出外层循环")
                break outer
            }
            fmt.Printf("i=%d, j=%d\n", i, j)
        }
    }
}

跳转语句

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package main

import "fmt"

func main() {
    // 1. break语句
    fmt.Println("1. break语句:")
    for i := 0; i < 10; i++ {
        if i == 5 {
            fmt.Println("遇到5,跳出循环")
            break
        }
        fmt.Printf("i = %d\n", i)
    }
    
    // 2. continue语句
    fmt.Println("\n2. continue语句:")
    for i := 0; i < 10; i++ {
        if i%2 == 0 {
            continue  // 跳过偶数
        }
        fmt.Printf("奇数: %d\n", i)
    }
    
    // 3. 带标签的break和continue
    fmt.Println("\n3. 带标签的break和continue:")
    
    // 带标签的break
    fmt.Println("带标签的break:")
outerLoop:
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            if i == 1 && j == 1 {
                fmt.Printf("在(%d,%d)处跳出外层循环\n", i, j)
                break outerLoop
            }
            fmt.Printf("(%d,%d) ", i, j)
        }
        fmt.Println()
    }
    
    // 带标签的continue
    fmt.Println("\n带标签的continue:")
outerLoop2:
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            if j == 1 {
                fmt.Printf("在(%d,%d)处继续外层循环\n", i, j)
                continue outerLoop2
            }
            fmt.Printf("(%d,%d) ", i, j)
        }
        fmt.Println("这行不会被打印")
    }
    
    // 4. goto语句(不推荐使用)
    fmt.Println("\n4. goto语句:")
    i := 0
loop:
    if i < 3 {
        fmt.Printf("i = %d\n", i)
        i++
        goto loop
    }
    fmt.Println("goto循环结束")
    
    // 5. return语句
    fmt.Println("\n5. return语句:")
    result := processNumbers([]int{1, 2, 3, 4, 5})
    fmt.Printf("处理结果: %d\n", result)
    
    // 6. defer语句(延迟执行)
    fmt.Println("\n6. defer语句:")
    deferExample()
    
    // 7. panic和recover
    fmt.Println("\n7. panic和recover:")
    recoverExample()
}

func processNumbers(numbers []int) int {
    sum := 0
    for _, num := range numbers {
        if num < 0 {
            fmt.Println("遇到负数,提前返回")
            return sum
        }
        sum += num
    }
    return sum
}

func deferExample() {
    fmt.Println("函数开始")
    
    defer fmt.Println("defer 1")  // 最后执行
    defer fmt.Println("defer 2")  // 倒数第二执行
    defer fmt.Println("defer 3")  // 倒数第三执行
    
    fmt.Println("函数中间")
    fmt.Println("函数结束")
    // defer语句按LIFO顺序执行
}

func recoverExample() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Printf("捕获到panic: %v\n", r)
        }
    }()
    
    fmt.Println("正常执行")
    panic("发生了panic")
    fmt.Println("这行不会执行")
}

控制流的最佳实践

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package main

import (
    "fmt"
    "strconv"
)

func main() {
    // 1. 早期返回模式
    fmt.Println("1. 早期返回模式:")
    result1 := validateAndProcess("123")
    fmt.Printf("结果1: %d\n", result1)
    
    result2 := validateAndProcess("abc")
    fmt.Printf("结果2: %d\n", result2)
    
    // 2. 避免深层嵌套
    fmt.Println("\n2. 避免深层嵌套:")
    processUser("admin", "123456", 25)
    processUser("", "123456", 25)
    processUser("admin", "123", 25)
    processUser("admin", "123456", 15)
    
    // 3. 使用switch替代长if-else链
    fmt.Println("\n3. 使用switch替代长if-else链:")
    for _, status := range []int{200, 404, 500, 301} {
        handleHTTPStatus(status)
    }
    
    // 4. 合理使用range
    fmt.Println("\n4. 合理使用range:")
    data := []string{"apple", "banana", "cherry"}
    
    // 需要索引时
    for i, item := range data {
        fmt.Printf("索引%d: %s\n", i, item)
    }
    
    // 只需要值时
    for _, item := range data {
        fmt.Printf("项目: %s\n", item)
    }
    
    // 只需要索引时
    for i := range data {
        fmt.Printf("索引: %d\n", i)
    }
    
    // 5. 错误处理模式
    fmt.Println("\n5. 错误处理模式:")
    if err := performOperation(); err != nil {
        fmt.Printf("操作失败: %v\n", err)
        return
    }
    fmt.Println("操作成功")
}

// 早期返回模式 - 避免深层嵌套
func validateAndProcess(input string) int {
    if input == "" {
        fmt.Println("输入为空")
        return 0
    }
    
    num, err := strconv.Atoi(input)
    if err != nil {
        fmt.Printf("转换失败: %v\n", err)
        return 0
    }
    
    if num < 0 {
        fmt.Println("数字不能为负")
        return 0
    }
    
    return num * 2
}

// 避免深层嵌套的用户处理函数
func processUser(username, password string, age int) {
    if username == "" {
        fmt.Println("用户名不能为空")
        return
    }
    
    if len(password) < 6 {
        fmt.Println("密码长度不能少于6位")
        return
    }
    
    if age < 18 {
        fmt.Println("年龄必须大于等于18岁")
        return
    }
    
    fmt.Printf("用户 %s 验证通过\n", username)
}

// 使用switch处理HTTP状态码
func handleHTTPStatus(status int) {
    switch {
    case status >= 200 && status < 300:
        fmt.Printf("状态码 %d: 成功\n", status)
    case status >= 300 && status < 400:
        fmt.Printf("状态码 %d: 重定向\n", status)
    case status >= 400 && status < 500:
        fmt.Printf("状态码 %d: 客户端错误\n", status)
    case status >= 500:
        fmt.Printf("状态码 %d: 服务器错误\n", status)
    default:
        fmt.Printf("状态码 %d: 未知状态\n", status)
    }
}

// 模拟可能出错的操作
func performOperation() error {
    // 这里可能会返回错误
    return nil
}

总结

  1. if语句

    • 支持初始化语句
    • 条件表达式不需要括号
    • 支持else if和else
    • 常用于错误检查和类型断言
  2. switch语句

    • 不需要break(默认不会fall through)
    • 支持多个case值
    • 支持无表达式的switch
    • 支持类型switch
    • 可以使用fallthrough关键字
  3. for循环

    • Go唯一的循环语句
    • 支持传统的三段式循环
    • 支持while风格的循环
    • 支持无限循环
    • range循环用于遍历集合类型
  4. 跳转语句

    • break:跳出循环或switch
    • continue:跳过当前迭代
    • goto:无条件跳转(不推荐)
    • return:从函数返回
    • defer:延迟执行
    • panic/recover:异常处理
  5. 最佳实践

    • 使用早期返回避免深层嵌套
    • 合理使用switch替代长if-else链
    • 正确使用range循环
    • 遵循Go的错误处理模式
updatedupdated2025-09-202025-09-20