Go 条件语句:if 与 switch
程序不可能永远直线走,经常要"看情况办事"——条件语句就是用来做分支选择的。Go 主要有 if/else 和 switch 两种,语法上比 C/Java 更简洁,也有几个自己的小规矩。本篇带你逐一掌握,并顺带认识 Go 独特的 Type Switch。
一、if 语句
Go 的 if 有两个明显特点:条件不用加括号,但花括号必须写——哪怕后面只有一行代码也不能省。而且左花括号 { 必须和 if 写在同一行,不能另起一行,否则编译直接报错(这是 Go 强制代码风格的体现)。
package main
import "fmt"
func main() {
score := 85
if score >= 90 {
fmt.Println("优秀")
} else if score >= 60 {
fmt.Println("及格")
} else {
fmt.Println("不及格")
}
}二、if 的初始化语句
Go 的 if 可以在条件前先执行一条初始化语句,中间用分号隔开。这非常适合"先算个值,再判断它"的场景,而且这个临时变量的作用域只在 if/else 块内,出了块就消失,保持外部命名空间干净。
package main
import "fmt"
func compute() int {
return 42
}
func main() {
// if 可以带一条初始化语句,用分号与条件隔开
if v := compute(); v > 100 {
fmt.Println("太大:", v)
} else {
fmt.Println("OK:", v) // v 在 else 分支里依然可用
}
// fmt.Println(v) // 编译错误:v 的作用域仅限于 if/else 块内
}这种写法在 Go 里到处可见,最典型的就是错误处理范式: if err := doSomething(); err != nil { ... }。先调用函数拿到 err,紧接着判断它是否为空,一行搞定,而且 err 不会污染外层作用域。
三、switch 语句
当一个变量要和很多种值比较时,写一长串 if/else if 会很丑,switch 更清晰。Go 的 switch 和 C/Java 有几个关键不同:
- 默认不穿透:每个
case执行完会自动break,不会继续往下走。 - 想要穿透时,必须显式写
fallthrough。 - 一个
case可以匹配多个值,用逗号分隔。 - 不需要 break,反而让代码更安全——忘写 break 不再是 bug。
package main
import "fmt"
func main() {
day := "Sat"
switch day {
case "Sat", "Sun": // 一个 case 匹配多个值,逗号分隔
fmt.Println("周末")
case "Mon", "Tue", "Wed", "Thu", "Fri":
fmt.Println("工作日")
default:
fmt.Println("未知")
}
}四、无条件 switch 与 fallthrough
switch 还可以不写表达式,把判断条件放在每个 case 里——相当于把 if/else 链换了一种排版,分支多时更整齐。配合 fallthrough 则可以强制"穿透"到下一个 case 的代码体(注意:fallthrough 不检查下个 case 的条件,无条件进入,而且只穿透一层)。
package main
import "fmt"
func main() {
// 1. 无条件 switch:省略表达式,等价于 if/else 链
n := -5
switch {
case n < 0:
fmt.Println("负数")
case n == 0:
fmt.Println("零")
default:
fmt.Println("正数")
}
// 2. fallthrough:强制进入下一个 case 的代码体(不检查条件)
x := 1
switch x {
case 1:
fmt.Println("一")
fallthrough
case 2:
fmt.Println("二") // 即使 x != 2,这里也会执行
}
}五、Type Switch(类型判断)
这是 Go 比较独特的一个用法。Go 的接口(interface)内部存着一个"动态类型",想在运行时知道它到底是什么类型,就用类型 switch。语法是 switch v := x.(type) { ... },每个 case 匹配一种类型,并且 v 在对应分支里会自动成为那种类型,用起来非常顺手。
package main
import "fmt"
// describe 接收任意类型的参数(空接口 interface{})
func describe(i interface{}) {
// 类型 switch:判断接口里实际存放的动态类型
switch v := i.(type) {
case int:
fmt.Println("整数,值 =", v)
case string:
fmt.Printf("字符串,长度 = %d\n", len(v))
case bool:
fmt.Println("布尔:", v)
default:
fmt.Printf("其它类型:%T\n", v)
}
}
func main() {
describe(42)
describe("hello")
describe(true)
describe(3.14)
}这在处理泛化数据(JSON 解析、通用容器、第三方库返回值)时非常有用,让你安全地对接口值做"类型分发"。除了 type switch,还有单值类型断言 v, ok := x.(int),ok 用来标识断言是否成功。
六、select 简单提及
除了 if 和 switch,Go 还有一个 select 语句,长得像 switch,但专门用于多个 channel 的选择——哪个 channel 先准备好就执行哪个分支。它是并发编程的核心控制结构,要等学到 channel 和 goroutine 时才能完全理解,这里先有个印象即可,暂不展开。
小结
if 条件不加括号、花括号必写、可带初始化语句;switch 默认不穿透、支持多值匹配和无条件写法;Type switch 用于判断接口的动态类型;select 留给并发。下一篇进入 Go 唯一的循环——for。