Switch 是 Go 语言中一种多路条件语句,一般搭配 case 语句使用。
执行逻辑
一个 switch case 条件结构如下所示:
switch simpleStatement; condition {
case expression1,expression2:
statements
case expression3:
statements
default:
statements
}
和 if 语句类似,switch 语句也可以在条件语句之前执行一段简短的表达式(可以用于很方便的控制变量的作用域),switch case 开始执行时,会先执行这一个表达式(空也算一种),然后计算出条件语句的值,接着按从上到下,从左到右的顺序一个一个的执行 case 语句的条件表达式,如果值相等的话就会进入执行 case 条件下对应的语句。
如果所有的 case 条件都没有能匹配上的话,然后就会尝试执行 default 下对应的逻辑。
case 条件合并
如果有时候多个 case 条件对应的处理逻辑是一样的话,Go 语言中的 case 条件是可以合并的,多个条件用逗号分隔,判断顺序是从左到右。
func main() {
switch runtime.GOOS {
case "linux","darwin" :
println("unix环境")
case "windows":
println("windows环境")
}
}
支持的类型
不像 Java 只支持整型进行判断(其他类型都是通过转化成整型实现的),Go 里的 switch 的参数是一个表达式,支持任何类型进行比较,甚至 switch 的条件还可以是一个空的,这个时候等价于 switch true,可以用于简化多个 if 条件的场景。
func price(weight int) int {
if weight > 10 {
return 100
} else if weight > 8 {
return 110
} else if weight > 5 {
return 120
} else {
return 150
}
}
比如上方这个多重 if else 判断逻辑就可以用下方这个无参数的 switch case 语句替代:
func price(weight int) int {
switch {
case weight>10:
return 100
case weight>8:
return 110
case weight>5:
return 120
default:
return 150
}
}
隐式 break & fallthrough
Go 语言中匹配到一个 case 条件执行完对应的逻辑之后就会跳出这个 switch 语句,等价于每个 case 处理逻辑之后都加了一个隐式的 break 语句。如果不想要隐式退出的话可以使用 fallthrough 语句来继续下一个 case 的处理逻辑。
隐式 break:
func main() {
switch runtime.GOOS {
case "linux","darwin" :
println("unix环境")
case "windows":
println("window环境")
default:
println("什么都不是")
}
}
输出:
windows环境
强行 fallthrough:
func main() {
switch runtime.GOOS {
case "linux","darwin" :
println("unix环境")
fallthrough
case "windows":
println("windows环境")
fallthrough // 会继续执行下一个语句
default:
println("什么都不是")
}
}
输出:
windows环境
什么都不是
不过这一点就和很多其他编程语言正好相反,比如:Java、C++。Java 和 C++ 中的 switch case 都是隐式 fallthrough,而break 则需要显示调用,这两种方式各有利弊吧,还是看不同的使用场景,不过 Java 12 中也加入了对于隐式 break 的支持。
另外 Go 语言中也是可以显示调用 break 提前跳出的,用法和循环语句中的 break 是一样的,也可以加标签指定跳出具体哪一段逻辑。
break 显式跳出:
func main() {
x := []int{1,2,3,4,5}
for _, i := range x {
switch {
case i>0 :
if i > 1 && i < 3 {
break
}
println(i)
}
}
}
输出:
1
3
4
5
指定标签跳出 for 循环:
func main() {
x := []int{1,2,3,4,5}
a:
for _, i := range x {
switch {
case i>0 :
if i > 1 && i < 3 {
break a
}
println(i)
}
}
}
输出:
1
Type Switch
Go 语言中的 switch 条件还可以是一种类型,这个特性在一个变量可能是多种类型时非常有用,虽然也可以 if else 加上类型断言来实现:
func main() {
i := interface{}(123)
if _,ok := i.(int);ok{
println("int")
}else if _,ok := i.(int64);ok {
println("int64")
}else if _,ok := i.(string);ok {
println("string")
}
}
但是用 Type Switch 的话代码会更简洁一些,比如上面的逻辑用 Type Switch 重写:
func main() {
i := interface{}(123)
switch i.(type) {
case int:
println("int")
case int64:
println("int64")
case float64:
println("float64")
}
}
输出:
int
(注:这里 123 是 int 类型而不是 int64,因为在申明变量时并没有指定具体类型,编译器会自行推导类型,而 int 是无类型整形的默认类型。)
同时 Type Switch 可以给赋值给一个变量,这个变量在不同的 case 中会变成对应 case 条件的类型(在合并了 case 语句之后会失效)
func main() {
var i interface{}
switch x := i.(type) {
case error:
x.Error()
case fmt.Stringer:
x.String()
}
}