600 lines
14 KiB
Go
600 lines
14 KiB
Go
/*
|
||
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. 类型判断和处理
|
||
*/ |