Skip to content

Go 语言条件语句

条件语句是程序控制流的重要组成部分,允许程序根据不同条件执行不同的代码路径。Go 语言提供了 ifswitch 两种主要的条件控制结构。

🔀 if 语句

基本 if 语句

go
package main

import "fmt"

func main() {
    age := 18
    
    // 基本 if 语句
    if age >= 18 {
        fmt.Println("你已经成年了")
    }
    
    // if-else 语句
    score := 85
    if score >= 90 {
        fmt.Println("优秀")
    } else {
        fmt.Println("良好")
    }
    
    // 多条件判断
    temperature := 25
    if temperature < 0 {
        fmt.Println("天气很冷")
    } else if temperature < 20 {
        fmt.Println("天气凉爽")
    } else if temperature < 30 {
        fmt.Println("天气温暖")
    } else {
        fmt.Println("天气炎热")
    }
}

if 语句的特殊语法

初始化语句

go
func main() {
    // if 语句可以包含一个初始化语句
    if num := 42; num > 0 {
        fmt.Printf("%d 是正数\n", num)
    }
    // 注意:num 变量只在 if 块内有效
    
    // 实际应用:处理函数返回值
    if result, err := divide(10, 2); err != nil {
        fmt.Printf("错误: %v\n", err)
    } else {
        fmt.Printf("结果: %.2f\n", result)
    }
    
    // 检查映射中的键
    userAges := map[string]int{
        "Alice": 25,
        "Bob":   30,
    }
    
    if age, exists := userAges["Alice"]; exists {
        fmt.Printf("Alice 的年龄是 %d\n", age)
    } else {
        fmt.Println("找不到 Alice 的年龄信息")
    }
}

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("除数不能为零")
    }
    return a / b, nil
}

复杂条件判断

go
import "strings"

func main() {
    // 逻辑运算符组合条件
    username := "admin"
    password := "123456"
    isActive := true
    
    if username == "admin" && password == "123456" && isActive {
        fmt.Println("管理员登录成功")
    } else {
        fmt.Println("登录失败")
    }
    
    // 字符串条件判断
    email := "user@example.com"
    if strings.Contains(email, "@") && strings.Contains(email, ".") {
        fmt.Println("邮箱格式看起来正确")
    } else {
        fmt.Println("邮箱格式不正确")
    }
    
    // 数值范围判断
    score := 95
    var grade string
    if score >= 90 {
        grade = "A"
    } else if score >= 80 {
        grade = "B"
    } else if score >= 70 {
        grade = "C"
    } else if score >= 60 {
        grade = "D"
    } else {
        grade = "F"
    }
    fmt.Printf("分数 %d 对应等级 %s\n", score, grade)
}

🔄 switch 语句

基本 switch 语句

go
func main() {
    // 基本 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("无效的日期")
    }
    
    // 字符串 switch
    operation := "add"
    switch operation {
    case "add":
        fmt.Println("执行加法运算")
    case "subtract":
        fmt.Println("执行减法运算")
    case "multiply":
        fmt.Println("执行乘法运算")
    case "divide":
        fmt.Println("执行除法运算")
    default:
        fmt.Println("未知运算")
    }
}

switch 语句的高级特性

带初始化的 switch

go
import "time"

func main() {
    // switch 语句可以包含初始化语句
    switch hour := time.Now().Hour(); {
    case hour < 6:
        fmt.Println("凌晨时光")
    case hour < 12:
        fmt.Println("上午时光")
    case hour < 18:
        fmt.Println("下午时光")
    default:
        fmt.Println("晚上时光")
    }
    
    // 在 switch 中调用函数
    switch result := calculateGrade(85); result {
    case "A":
        fmt.Println("优秀成绩!")
    case "B":
        fmt.Println("良好成绩!")
    case "C":
        fmt.Println("及格成绩!")
    default:
        fmt.Println("需要努力!")
    }
}

func calculateGrade(score int) string {
    if score >= 90 {
        return "A"
    } else if score >= 80 {
        return "B"
    } else if score >= 70 {
        return "C"
    }
    return "D"
}

无表达式的 switch

go
func main() {
    x := 15
    
    // 无表达式的 switch(相当于 if-else 链)
    switch {
    case x < 0:
        fmt.Println("x 是负数")
    case x == 0:
        fmt.Println("x 是零")
    case x > 0 && x < 10:
        fmt.Println("x 是个位正数")
    case x >= 10 && x < 100:
        fmt.Println("x 是两位正数")
    default:
        fmt.Println("x 是大于等于100的数")
    }
    
    // 复杂条件判断
    temperature := 25
    humidity := 60
    
    switch {
    case temperature > 30 && humidity > 70:
        fmt.Println("又热又湿,不舒适")
    case temperature > 30:
        fmt.Println("天气炎热")
    case temperature < 10:
        fmt.Println("天气寒冷")
    case humidity > 80:
        fmt.Println("湿度很高")
    default:
        fmt.Println("天气适宜")
    }
}

fallthrough 关键字

go
func main() {
    grade := "B"
    
    // fallthrough 会继续执行下一个 case
    switch grade {
    case "A":
        fmt.Println("优秀!")
        fallthrough
    case "B":
        fmt.Println("良好!")
        fallthrough
    case "C":
        fmt.Println("及格!")
        // 没有 fallthrough,不会继续执行
    case "D":
        fmt.Println("不及格!")
    default:
        fmt.Println("无效等级")
    }
    
    // 输出:
    // 良好!
    // 及格!
    
    // 注意:fallthrough 必须是 case 块的最后一条语句
    processNumber := func(n int) {
        switch n {
        case 1:
            fmt.Println("处理数字 1")
            // 一些逻辑处理
            fallthrough
        case 2:
            fmt.Println("数字 1 和 2 的通用处理")
        case 3:
            fmt.Println("处理数字 3")
        }
    }
    
    processNumber(1)
    fmt.Println("---")
    processNumber(2)
}

类型 switch

go
import "fmt"

func main() {
    // 类型 switch 用于判断接口变量的实际类型
    var x interface{} = 42
    
    switch v := x.(type) {
    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)
    case float64:
        fmt.Printf("x 是 float64 类型,值为 %f\n", v)
    default:
        fmt.Printf("x 是未知类型 %T\n", v)
    }
    
    // 处理不同类型的数据
    processValue := func(value interface{}) {
        switch v := value.(type) {
        case nil:
            fmt.Println("值是 nil")
        case int, int32, int64:
            fmt.Printf("整数值: %v\n", v)
        case float32, float64:
            fmt.Printf("浮点数值: %v\n", v)
        case string:
            fmt.Printf("字符串值: %q\n", v)
        case []int:
            fmt.Printf("整数切片: %v\n", v)
        default:
            fmt.Printf("未处理的类型: %T\n", v)
        }
    }
    
    processValue(42)
    processValue(3.14)
    processValue("hello")
    processValue([]int{1, 2, 3})
    processValue(true)
}

🎯 实际应用示例

用户权限验证系统

go
import (
    "fmt"
    "strings"
)

// 用户角色
const (
    RoleAdmin = "admin"
    RoleUser  = "user"
    RoleGuest = "guest"
)

// 权限级别
const (
    PermissionNone   = 0
    PermissionRead   = 1
    PermissionWrite  = 2
    PermissionDelete = 3
)

type User struct {
    Username   string
    Role       string
    IsActive   bool
    Permission int
}

func main() {
    users := []User{
        {"admin", RoleAdmin, true, PermissionDelete},
        {"john", RoleUser, true, PermissionWrite},
        {"guest", RoleGuest, true, PermissionRead},
        {"inactive", RoleUser, false, PermissionWrite},
    }
    
    for _, user := range users {
        checkUserAccess(user, "delete_file")
        fmt.Println("---")
    }
}

func checkUserAccess(user User, action string) {
    // 首先检查用户是否激活
    if !user.IsActive {
        fmt.Printf("用户 %s 账户未激活,拒绝访问\n", user.Username)
        return
    }
    
    // 基于角色的访问控制
    switch user.Role {
    case RoleAdmin:
        fmt.Printf("管理员 %s 拥有所有权限\n", user.Username)
        performAction(action)
    case RoleUser:
        // 检查具体权限
        if checkPermission(user.Permission, action) {
            fmt.Printf("用户 %s 有权限执行 %s\n", user.Username, action)
            performAction(action)
        } else {
            fmt.Printf("用户 %s 权限不足,无法执行 %s\n", user.Username, action)
        }
    case RoleGuest:
        // 访客只能读取
        if strings.HasPrefix(action, "read") {
            fmt.Printf("访客 %s 可以执行只读操作 %s\n", user.Username, action)
            performAction(action)
        } else {
            fmt.Printf("访客 %s 只能执行只读操作\n", user.Username)
        }
    default:
        fmt.Printf("未知角色,拒绝访问\n")
    }
}

func checkPermission(userPermission int, action string) bool {
    switch action {
    case "read_file", "view_data":
        return userPermission >= PermissionRead
    case "write_file", "update_data":
        return userPermission >= PermissionWrite
    case "delete_file", "delete_data":
        return userPermission >= PermissionDelete
    default:
        return false
    }
}

func performAction(action string) {
    fmt.Printf("  -> 执行操作: %s\n", action)
}

HTTP 状态码处理

go
import (
    "fmt"
    "net/http"
)

func main() {
    // 模拟不同的 HTTP 状态码
    statusCodes := []int{200, 201, 400, 401, 403, 404, 500, 502, 503}
    
    for _, code := range statusCodes {
        handleHTTPStatus(code)
    }
}

func handleHTTPStatus(statusCode int) {
    fmt.Printf("处理状态码 %d: ", statusCode)
    
    switch {
    case statusCode >= 200 && statusCode < 300:
        // 2xx 成功状态码
        switch statusCode {
        case http.StatusOK:
            fmt.Println("请求成功")
        case http.StatusCreated:
            fmt.Println("资源创建成功")
        case http.StatusAccepted:
            fmt.Println("请求已接受")
        case http.StatusNoContent:
            fmt.Println("请求成功,无内容返回")
        default:
            fmt.Println("其他成功状态")
        }
        
    case statusCode >= 300 && statusCode < 400:
        // 3xx 重定向状态码
        fmt.Println("需要重定向")
        
    case statusCode >= 400 && statusCode < 500:
        // 4xx 客户端错误
        switch statusCode {
        case http.StatusBadRequest:
            fmt.Println("请求参数错误")
        case http.StatusUnauthorized:
            fmt.Println("需要身份验证")
        case http.StatusForbidden:
            fmt.Println("禁止访问")
        case http.StatusNotFound:
            fmt.Println("资源不存在")
        case http.StatusMethodNotAllowed:
            fmt.Println("请求方法不允许")
        default:
            fmt.Println("其他客户端错误")
        }
        
    case statusCode >= 500:
        // 5xx 服务器错误
        switch statusCode {
        case http.StatusInternalServerError:
            fmt.Println("服务器内部错误")
        case http.StatusBadGateway:
            fmt.Println("网关错误")
        case http.StatusServiceUnavailable:
            fmt.Println("服务不可用")
        case http.StatusGatewayTimeout:
            fmt.Println("网关超时")
        default:
            fmt.Println("其他服务器错误")
        }
        
    default:
        fmt.Println("未知状态码")
    }
}

计算器应用

go
import (
    "fmt"
    "math"
)

func main() {
    calculator := NewCalculator()
    
    // 测试各种运算
    testCases := []struct {
        a, b      float64
        operation string
    }{
        {10, 5, "add"},
        {10, 5, "subtract"},
        {10, 5, "multiply"},
        {10, 5, "divide"},
        {10, 0, "divide"}, // 除零测试
        {16, 0, "sqrt"},
        {2, 8, "power"},
        {10, 5, "unknown"}, // 未知操作
    }
    
    for _, test := range testCases {
        result, err := calculator.Calculate(test.a, test.b, test.operation)
        if err != nil {
            fmt.Printf("%.1f %s %.1f = 错误: %v\n", test.a, test.operation, test.b, err)
        } else {
            if test.operation == "sqrt" {
                fmt.Printf("%s(%.1f) = %.2f\n", test.operation, test.a, result)
            } else {
                fmt.Printf("%.1f %s %.1f = %.2f\n", test.a, test.operation, test.b, result)
            }
        }
    }
}

type Calculator struct{}

func NewCalculator() *Calculator {
    return &Calculator{}
}

func (c *Calculator) Calculate(a, b float64, operation string) (float64, error) {
    switch operation {
    case "add", "+":
        return a + b, nil
        
    case "subtract", "-":
        return a - b, nil
        
    case "multiply", "*":
        return a * b, nil
        
    case "divide", "/":
        if b == 0 {
            return 0, fmt.Errorf("除数不能为零")
        }
        return a / b, nil
        
    case "power", "^":
        return math.Pow(a, b), nil
        
    case "sqrt":
        if a < 0 {
            return 0, fmt.Errorf("负数没有实数平方根")
        }
        return math.Sqrt(a), nil
        
    case "mod", "%":
        if b == 0 {
            return 0, fmt.Errorf("模数不能为零")
        }
        return math.Mod(a, b), nil
        
    default:
        return 0, fmt.Errorf("不支持的运算: %s", operation)
    }
}

💡 最佳实践

条件语句的优化

go
func main() {
    // ❌ 避免深层嵌套
    badExample := func(user User) {
        if user.IsActive {
            if user.Role == "admin" {
                if user.Permission >= PermissionWrite {
                    fmt.Println("允许访问")
                } else {
                    fmt.Println("权限不足")
                }
            } else {
                fmt.Println("非管理员")
            }
        } else {
            fmt.Println("用户未激活")
        }
    }
    
    // ✅ 使用早期返回
    goodExample := func(user User) {
        if !user.IsActive {
            fmt.Println("用户未激活")
            return
        }
        
        if user.Role != "admin" {
            fmt.Println("非管理员")
            return
        }
        
        if user.Permission < PermissionWrite {
            fmt.Println("权限不足")
            return
        }
        
        fmt.Println("允许访问")
    }
    
    testUser := User{"test", RoleAdmin, true, PermissionWrite}
    
    fmt.Println("坏的示例:")
    badExample(testUser)
    
    fmt.Println("好的示例:")
    goodExample(testUser)
}

使用 switch 替代长 if-else 链

go
func main() {
    // ❌ 长 if-else 链
    gradeToGPA_Bad := func(grade string) float64 {
        if grade == "A+" {
            return 4.0
        } else if grade == "A" {
            return 4.0
        } else if grade == "A-" {
            return 3.7
        } else if grade == "B+" {
            return 3.3
        } else if grade == "B" {
            return 3.0
        } else if grade == "B-" {
            return 2.7
        } else if grade == "C+" {
            return 2.3
        } else if grade == "C" {
            return 2.0
        } else if grade == "C-" {
            return 1.7
        } else if grade == "D" {
            return 1.0
        } else {
            return 0.0
        }
    }
    
    // ✅ 使用 switch
    gradeToGPA_Good := func(grade string) float64 {
        switch grade {
        case "A+", "A":
            return 4.0
        case "A-":
            return 3.7
        case "B+":
            return 3.3
        case "B":
            return 3.0
        case "B-":
            return 2.7
        case "C+":
            return 2.3
        case "C":
            return 2.0
        case "C-":
            return 1.7
        case "D":
            return 1.0
        default:
            return 0.0
        }
    }
    
    grades := []string{"A", "B+", "C", "D", "F"}
    
    fmt.Println("成绩转GPA:")
    for _, grade := range grades {
        gpa1 := gradeToGPA_Bad(grade)
        gpa2 := gradeToGPA_Good(grade)
        fmt.Printf("%s: %.1f (两种方法结果相同: %t)\n", grade, gpa1, gpa1 == gpa2)
    }
}

🎓 小结

本章我们全面学习了 Go 语言的条件语句:

  • if 语句:基本语法、初始化语句、复杂条件判断
  • switch 语句:基本用法、多值匹配、无表达式switch
  • 特殊特性:fallthrough关键字、类型switch
  • 实际应用:权限系统、状态处理、计算器应用
  • 最佳实践:避免深层嵌套、优化条件链

条件语句是程序逻辑控制的核心,正确使用能让代码更清晰、更高效。


接下来,我们将学习 Go 语言循环语句,掌握程序的重复执行控制。

条件语句使用建议

  • 优先使用早期返回避免深层嵌套
  • 长 if-else 链可以考虑用 switch 替代
  • 善用 switch 的初始化语句和类型判断
  • 注意 fallthrough 的使用场景和限制

本站内容仅供学习和研究使用。