Files
2025-08-24 01:01:26 +08:00

600 lines
14 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
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. 类型判断和处理
*/