/* 02-switch.go - Go 语言 switch 语句详解 学习目标: 1. 掌握 switch 语句的基本用法 2. 理解 Go switch 的特殊特性 3. 学会使用 fallthrough 关键字 4. 了解类型 switch 的用法 5. 掌握无表达式 switch 的使用 知识点: - switch 基本语法 - case 多值匹配 - fallthrough 关键字 - 类型 switch - 无表达式 switch - switch 中的变量声明 - 实际应用场景 */ package main import ( "fmt" "math/rand" "time" ) func main() { fmt.Println("=== Go 语言 switch 语句详解 ===\n") // 演示基本 switch 语句 demonstrateBasicSwitch() // 演示多值 case demonstrateMultiValueCase() // 演示 fallthrough demonstrateFallthrough() // 演示无表达式 switch demonstrateExpressionlessSwitch() // 演示类型 switch demonstrateTypeSwitch() // 演示 switch 中的变量声明 demonstrateSwitchWithDeclaration() // 演示实际应用示例 demonstratePracticalExamples() } // demonstrateBasicSwitch 演示基本 switch 语句 func demonstrateBasicSwitch() { fmt.Println("1. 基本 switch 语句:") // 基本用法 day := 3 fmt.Printf(" 今天是星期 %d: ", day) switch day { case 1: fmt.Printf("星期一\n") case 2: fmt.Printf("星期二\n") case 3: fmt.Printf("星期三\n") case 4: fmt.Printf("星期四\n") case 5: fmt.Printf("星期五\n") case 6: fmt.Printf("星期六\n") case 7: fmt.Printf("星期日\n") default: fmt.Printf("无效的日期\n") } // 字符串匹配 grade := "B" fmt.Printf(" 成绩等级 %s: ", grade) switch grade { case "A": fmt.Printf("优秀 (90-100分)\n") case "B": fmt.Printf("良好 (80-89分)\n") case "C": fmt.Printf("中等 (70-79分)\n") case "D": fmt.Printf("及格 (60-69分)\n") case "F": fmt.Printf("不及格 (0-59分)\n") default: fmt.Printf("无效等级\n") } // 字符匹配 char := 'a' fmt.Printf(" 字符 '%c' 是: ", char) switch char { case 'a', 'e', 'i', 'o', 'u': fmt.Printf("元音字母\n") default: fmt.Printf("辅音字母或其他字符\n") } // Go switch 的特点:自动 break fmt.Printf(" Go switch 特点: 每个 case 自动 break,不会继续执行下一个 case\n") fmt.Println() } // demonstrateMultiValueCase 演示多值 case func demonstrateMultiValueCase() { fmt.Println("2. 多值 case:") // 数字分组 number := 4 fmt.Printf(" 数字 %d 属于: ", number) switch number { case 1, 3, 5, 7, 9: fmt.Printf("奇数\n") case 2, 4, 6, 8, 10: fmt.Printf("偶数\n") case 0: fmt.Printf("零\n") default: fmt.Printf("其他数字\n") } // 月份分组 month := 7 fmt.Printf(" %d月属于: ", month) switch month { case 12, 1, 2: fmt.Printf("冬季\n") case 3, 4, 5: fmt.Printf("春季\n") case 6, 7, 8: fmt.Printf("夏季\n") case 9, 10, 11: fmt.Printf("秋季\n") default: fmt.Printf("无效月份\n") } // 工作日分组 weekday := "Saturday" fmt.Printf(" %s 是: ", weekday) switch weekday { case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday": fmt.Printf("工作日\n") case "Saturday", "Sunday": fmt.Printf("周末\n") default: fmt.Printf("无效日期\n") } // HTTP 状态码分组 statusCode := 404 fmt.Printf(" HTTP 状态码 %d: ", statusCode) switch statusCode { case 200, 201, 202, 204: fmt.Printf("成功响应\n") case 301, 302, 304: fmt.Printf("重定向\n") case 400, 401, 403, 404: fmt.Printf("客户端错误\n") case 500, 501, 502, 503: fmt.Printf("服务器错误\n") default: fmt.Printf("其他状态码\n") } fmt.Println() } // demonstrateFallthrough 演示 fallthrough 关键字 func demonstrateFallthrough() { fmt.Println("3. fallthrough 关键字:") fmt.Printf(" fallthrough 让程序继续执行下一个 case\n") score := 85 fmt.Printf(" 分数 %d 的评价:\n", score) switch { case score >= 90: fmt.Printf(" 优秀\n") fallthrough case score >= 80: fmt.Printf(" 良好\n") fallthrough case score >= 70: fmt.Printf(" 中等\n") fallthrough case score >= 60: fmt.Printf(" 及格\n") default: fmt.Printf(" 不及格\n") } // 另一个 fallthrough 示例 level := 2 fmt.Printf(" 用户等级 %d 的权限:\n", level) switch level { case 3: fmt.Printf(" - 管理员权限\n") fallthrough case 2: fmt.Printf(" - 编辑权限\n") fallthrough case 1: fmt.Printf(" - 查看权限\n") case 0: fmt.Printf(" - 无权限\n") } // 注意事项 fmt.Printf(" 注意: fallthrough 只能在 case 的最后一行使用\n") fmt.Printf(" 注意: fallthrough 会无条件执行下一个 case\n") fmt.Println() } // demonstrateExpressionlessSwitch 演示无表达式 switch func demonstrateExpressionlessSwitch() { fmt.Println("4. 无表达式 switch:") fmt.Printf(" 无表达式 switch 相当于 switch true,可以替代长的 if-else if 链\n") // 年龄分组 age := 25 fmt.Printf(" 年龄 %d 岁: ", age) switch { case age < 13: fmt.Printf("儿童\n") case age < 20: fmt.Printf("青少年\n") case age < 60: fmt.Printf("成年人\n") default: fmt.Printf("老年人\n") } // 温度判断 temperature := 28 fmt.Printf(" 温度 %d°C: ", temperature) switch { case temperature < 0: fmt.Printf("冰点以下\n") case temperature < 10: fmt.Printf("寒冷\n") case temperature < 20: fmt.Printf("凉爽\n") case temperature < 30: fmt.Printf("温暖\n") default: fmt.Printf("炎热\n") } // 复杂条件 hour := 14 isWeekend := false fmt.Printf(" 时间 %d:00, 周末: %t - ", hour, isWeekend) switch { case hour < 6: fmt.Printf("深夜时间\n") case hour < 12 && !isWeekend: fmt.Printf("工作上午\n") case hour < 12 && isWeekend: fmt.Printf("周末上午\n") case hour < 18 && !isWeekend: fmt.Printf("工作下午\n") case hour < 18 && isWeekend: fmt.Printf("周末下午\n") case hour < 22: fmt.Printf("晚上时间\n") default: fmt.Printf("夜晚时间\n") } // 数值范围判断 value := 75 fmt.Printf(" 数值 %d: ", value) switch { case value < 0: fmt.Printf("负数\n") case value == 0: fmt.Printf("零\n") case value <= 50: fmt.Printf("小数值 (1-50)\n") case value <= 100: fmt.Printf("中等数值 (51-100)\n") default: fmt.Printf("大数值 (>100)\n") } fmt.Println() } // demonstrateTypeSwitch 演示类型 switch func demonstrateTypeSwitch() { fmt.Println("5. 类型 switch:") fmt.Printf(" 类型 switch 用于判断接口变量的实际类型\n") // 定义不同类型的变量 values := []interface{}{ 42, "hello", 3.14, true, []int{1, 2, 3}, map[string]int{"a": 1}, nil, } for i, v := range values { fmt.Printf(" 值 %d: %v - ", i+1, v) switch t := v.(type) { case nil: fmt.Printf("nil 类型\n") case bool: fmt.Printf("布尔类型: %t\n", t) case int: fmt.Printf("整数类型: %d\n", t) case string: fmt.Printf("字符串类型: \"%s\" (长度: %d)\n", t, len(t)) case float64: fmt.Printf("浮点类型: %.2f\n", t) case []int: fmt.Printf("整数切片: %v (长度: %d)\n", t, len(t)) case map[string]int: fmt.Printf("字符串到整数的映射: %v\n", t) default: fmt.Printf("未知类型: %T\n", t) } } // 类型 switch 的另一种用法 fmt.Printf(" 处理不同类型的数据:\n") processValue(42) processValue("Go语言") processValue(3.14159) processValue([]string{"a", "b", "c"}) fmt.Println() } // demonstrateSwitchWithDeclaration 演示 switch 中的变量声明 func demonstrateSwitchWithDeclaration() { fmt.Println("6. switch 中的变量声明:") // 在 switch 中声明变量 fmt.Printf(" 在 switch 中声明变量:\n") switch num := rand.Intn(10); { case num < 3: fmt.Printf(" 随机数 %d < 3,小数值\n", num) case num < 7: fmt.Printf(" 随机数 %d 在 3-6 之间,中等数值\n", num) default: fmt.Printf(" 随机数 %d >= 7,大数值\n", num) } // 计算并判断 switch result := calculateGrade(85); result { case "A": fmt.Printf(" 成绩优秀: %s\n", result) case "B": fmt.Printf(" 成绩良好: %s\n", result) case "C": fmt.Printf(" 成绩中等: %s\n", result) default: fmt.Printf(" 成绩: %s\n", result) } // 字符串处理 switch length := len("Hello, World!"); { case length < 5: fmt.Printf(" 字符串长度 %d,较短\n", length) case length < 10: fmt.Printf(" 字符串长度 %d,中等\n", length) default: fmt.Printf(" 字符串长度 %d,较长\n", length) } fmt.Println() } // demonstratePracticalExamples 演示实际应用示例 func demonstratePracticalExamples() { fmt.Println("7. 实际应用示例:") // 示例1: HTTP 请求处理 fmt.Printf(" 示例1 - HTTP 请求处理:\n") method := "POST" path := "/api/users" switch method { case "GET": fmt.Printf(" 处理 GET 请求: 获取资源 %s\n", path) case "POST": fmt.Printf(" 处理 POST 请求: 创建资源 %s\n", path) case "PUT": fmt.Printf(" 处理 PUT 请求: 更新资源 %s\n", path) case "DELETE": fmt.Printf(" 处理 DELETE 请求: 删除资源 %s\n", path) default: fmt.Printf(" 不支持的 HTTP 方法: %s\n", method) } // 示例2: 文件扩展名处理 fmt.Printf(" 示例2 - 文件类型判断:\n") filename := "document.pdf" var fileType string switch { case hasExtension(filename, ".txt", ".md", ".doc", ".docx"): fileType = "文档文件" case hasExtension(filename, ".jpg", ".png", ".gif", ".bmp"): fileType = "图片文件" case hasExtension(filename, ".mp4", ".avi", ".mov", ".wmv"): fileType = "视频文件" case hasExtension(filename, ".mp3", ".wav", ".flac", ".aac"): fileType = "音频文件" case hasExtension(filename, ".pdf"): fileType = "PDF文件" case hasExtension(filename, ".zip", ".rar", ".7z", ".tar"): fileType = "压缩文件" default: fileType = "未知文件类型" } fmt.Printf(" 文件 \"%s\" 是 %s\n", filename, fileType) // 示例3: 游戏状态机 fmt.Printf(" 示例3 - 游戏状态处理:\n") gameState := "playing" playerHealth := 30 switch gameState { case "menu": fmt.Printf(" 显示主菜单\n") case "playing": fmt.Printf(" 游戏进行中\n") switch { case playerHealth <= 0: fmt.Printf(" 玩家死亡,游戏结束\n") case playerHealth < 20: fmt.Printf(" 玩家生命值低 (%d),危险状态\n", playerHealth) case playerHealth < 50: fmt.Printf(" 玩家生命值中等 (%d),注意安全\n", playerHealth) default: fmt.Printf(" 玩家状态良好 (%d)\n", playerHealth) } case "paused": fmt.Printf(" 游戏暂停\n") case "gameover": fmt.Printf(" 游戏结束\n") default: fmt.Printf(" 未知游戏状态: %s\n", gameState) } // 示例4: 错误码处理 fmt.Printf(" 示例4 - 错误码处理:\n") errorCode := 1001 switch errorCode { case 0: fmt.Printf(" 操作成功\n") case 1000, 1001, 1002: fmt.Printf(" 用户相关错误 (错误码: %d)\n", errorCode) switch errorCode { case 1000: fmt.Printf(" 用户不存在\n") case 1001: fmt.Printf(" 密码错误\n") case 1002: fmt.Printf(" 账户被锁定\n") } case 2000, 2001, 2002: fmt.Printf(" 权限相关错误 (错误码: %d)\n", errorCode) case 3000, 3001, 3002: fmt.Printf(" 数据相关错误 (错误码: %d)\n", errorCode) default: fmt.Printf(" 未知错误 (错误码: %d)\n", errorCode) } // 示例5: 配置解析 fmt.Printf(" 示例5 - 配置解析:\n") config := map[string]interface{}{ "debug": true, "port": 8080, "database": "mysql", "timeout": 30.5, } for key, value := range config { fmt.Printf(" 配置项 %s: ", key) switch v := value.(type) { case bool: if v { fmt.Printf("启用\n") } else { fmt.Printf("禁用\n") } case int: fmt.Printf("数值 %d\n", v) case float64: fmt.Printf("浮点数 %.1f\n", v) case string: fmt.Printf("字符串 \"%s\"\n", v) default: fmt.Printf("未知类型 %T\n", v) } } fmt.Println() } // 辅助函数 func processValue(v interface{}) { switch val := v.(type) { case int: fmt.Printf(" 处理整数: %d,平方: %d\n", val, val*val) case string: fmt.Printf(" 处理字符串: \"%s\",长度: %d\n", val, len(val)) case float64: fmt.Printf(" 处理浮点数: %.3f,四舍五入: %.0f\n", val, val) case []string: fmt.Printf(" 处理字符串切片: %v,元素个数: %d\n", val, len(val)) default: fmt.Printf(" 无法处理的类型: %T\n", val) } } func calculateGrade(score int) string { switch { case score >= 90: return "A" case score >= 80: return "B" case score >= 70: return "C" case score >= 60: return "D" default: return "F" } } func hasExtension(filename string, extensions ...string) bool { for _, ext := range extensions { if len(filename) >= len(ext) && filename[len(filename)-len(ext):] == ext { return true } } return false } func init() { rand.Seed(time.Now().UnixNano()) } /* 运行这个程序: go run 02-switch.go 学习要点: 1. Go 的 switch 语句自动 break,不需要显式写 break 2. case 可以包含多个值,用逗号分隔 3. fallthrough 关键字可以让程序继续执行下一个 case 4. 无表达式 switch 相当于 switch true,可以替代长的 if-else if 链 5. 类型 switch 用于判断接口变量的实际类型 6. 可以在 switch 语句中声明变量 Go switch 的优势: 1. 比长的 if-else if 链更清晰 2. 自动 break 避免了忘记 break 的错误 3. 支持多值 case,代码更简洁 4. 类型 switch 提供了强大的类型判断能力 5. 无表达式 switch 提供了灵活的条件判断 使用建议: 1. 当有多个固定值需要判断时,优先使用 switch 2. 当条件复杂时,使用无表达式 switch 3. 处理接口类型时,使用类型 switch 4. 谨慎使用 fallthrough,确保逻辑正确 5. 合理使用 default 分支处理异常情况 常见应用场景: 1. 状态机实现 2. 错误码处理 3. 文件类型判断 4. HTTP 请求路由 5. 配置解析 6. 类型判断和处理 */