Golang 流程控制

一、条件语句

1. if-else 语句

(1)基本语法

if 布尔表达式1 {
    // 布尔表达式1为真时执行
} else if 布尔表达式2 {
    // 布尔表达式1为假、布尔表达式2为真时执行
} else {
    // 所有布尔表达式都为假时执行
}

(2)注意事项

  • Go 中的布尔表达式无需使用括号 ()
  • 大括号 {} 必须存在,即使只有一行语句
  • 左括号 { 必须与 ifelse 在同一行
  • if 之后、条件语句之前,可添加变量初始化语句,用分号 ; 分隔,例如:if age := 20; age >= 18 { ... }
  • 不能用 0 或非 0 表示真假,必须显式使用布尔表达式

(3)示例

// 简单判断
var flag = true
if flag {
    fmt.Println("true")
} else {
    fmt.Println("false")
}

// 多条件判断
age := 17
if age >= 18 {
    fmt.Println("adult")
} else if age >= 15 {
    fmt.Println("not a adult")
} else {
    fmt.Println("other")
}

// 带变量初始化的判断
if age2 := 20; age2 >= 18 {
    fmt.Println("adult")
}

2. switch-case-default 语句

(1)基本语法

switch 变量 {
case 值1:
    // 变量等于值1时执行
case 值2, 值3:  // 支持多条件匹配
    // 变量等于值2或值3时执行
default:
    // 变量不匹配任何case时执行
}

(2)特殊关键字 fallthrough

  • 用于实现 case 穿透,即执行当前 case 后继续执行下一个 case
  • 若不使用 fallthrough,Go 的 switch 默认只执行匹配的一个 case(与 C++ 不同,无需显式 break)

(3)注意事项

  • case 可以是表达式(此时 switch 后可省略变量)
  • 可使用 break 终止当前 case 及后续执行(包括 fallthrough 后的语句)

(4)示例

// 多条件匹配
day := 3
switch day {
case 1, 2, 3, 4, 5:
    fmt.Println("workday")
default:
    fmt.Println("weekend")
}

// case 为表达式
score := 100
switch {
case score >= 100:
    fmt.Println(">= 100")
    fallthrough  // 穿透到下一个case
case score >= 90 && score < 95:
    fmt.Println(">= 90 && < 95")
default:
    fmt.Println("other")
}

3. select-case-default 语句

(1)基本语法

select {
case 操作1:  // 通常为通道操作
    // 操作1可执行时执行
case 操作2:
    // 操作2可执行时执行
default:
    // 所有操作都不可执行时执行(可选)
}

(2)特点

  • 类似 switch,但专门用于处理通道(channel)操作
  • 随机执行一个可运行的 case;若没有可运行的 case 且无 default,则会阻塞,直到有 case 可运行

(3)示例

package main

import (
    "fmt"
    "time"
)

var chanInt = make(chan int)
var chanStr = make(chan string)

func main() {
    go func() {
        chanInt <- 100
        chanStr <- "hello"
        close(chanInt)
        close(chanStr)
    }()

    for {
        select {
        case r := <-chanInt:
            fmt.Printf("chanInt: %v\n", r)
        case r := <-chanStr:
            fmt.Printf("chanStr: %v\n", r)
        default:
            fmt.Printf("default...\n")
        }
        time.Sleep(time.Second)
    }
}

二、循环语句

Go 语言中只有 for 循环,无 while、do-while 循环。

1. 普通 for 循环

(1)基本语法

// 完整形式:初始语句; 条件表达式; 结束语句
for i := 0; i < 10; i++ {
    // 循环体
}

// 省略初始和结束语句(类似 while 循环)
i := 0
for i < 10 {
    fmt.Printf("%v ", i)
    i++
}

// 无限循环(类似 while(true))
for {
    // 循环体(需内部用 break 终止)
}

2. for range 循环

(1)基本语法

for 索引/键, 值 := range 遍历对象 {
    // 循环体
}

(2)适用场景及返回值

  • 数组/切片:返回索引和对应值
  • 字符串:返回索引和对应字符(rune 类型)
  • map:返回键和对应值
  • 通道(channel):只返回通道内的值

(3)示例

// 遍历数组
var arr = [5]int{1, 2, 3, 4, 5}
for i, v := range arr {
    fmt.Printf("%v: %v, ", i, v)
}

// 遍历字符串
var str = "abc def"
for i, v := range str {
    fmt.Printf("%d: %c, ", i, v)
}

// 遍历切片
var slice = []int{1, 2, 3, 4, 5}
for i, v := range slice {
    fmt.Printf("%v: %v, ", i, v)
}

// 遍历 map
m := make(map[string]string)
m["name"] = "tom"
m["age"] = "20"
for k, v := range m {
    fmt.Printf("%v: %v, ", k, v)
}

三、流程控制关键字

1. break

  • 作用:结束当前 for、switch、select 的代码块
  • 注意事项:
    • 单独在 select 或无 fallthrough 的 switch 中,break 可有可无
    • 在有 fallthrough 的 switch 中,break 可终止后续语句执行
    • 带标签的 break 可跳出多层嵌套的代码块(如多层循环、switch 等)
// 带标签的 break 跳出多层循环
MY_LABEL:
for i := 0; i < 10; i++ {
    if i == 5 {
        break MY_LABEL  // 直接跳出 MY_LABEL 标记的循环
    }
    fmt.Printf("%d ", i)
}

2. continue

  • 作用:只能用于 for 循环,跳过当前循环的剩余部分,直接进入下一轮循环
  • 支持带标签,跳过标签标记的循环的当前轮次
for i := 0; i < 5; i++ {
MY_LABEL:
    for j := 0; j < 5; j++ {
        if i == 2 && j == 3 {
            continue MY_LABEL  // 跳过当前 i=2、j=3 所在的内层循环轮次
        }
        fmt.Printf("%d-%d ", i, j)
    }
    fmt.Println()
}

3. goto

  • 作用:跳转到代码中指定的标签位置(标签需单独一行,格式为 标签名:
  • 注意:避免滥用,以免导致代码逻辑混乱
a := 1
if a == 1 {
    goto LABEL1  // 跳转到 LABEL1
} else {
    fmt.Println("not 1")
}

LABEL1:
fmt.Println("=1")