Files
the-way-to-go_ZH_CN/eBook/05.3.md
2015-01-23 23:31:06 +08:00

194 lines
4.8 KiB
Markdown
Raw 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.

# 5.3 switch 结构
相比较 C 和 Java 等其它语言而言Go 语言中的 switch 结构使用上更加灵活。它接受任意形式的表达式:
```
switch var1 {
case val1:
...
case val2:
...
default:
...
}
```
变量 var1 可以是任何类型,而 val1 和 val2 则可以是同类型的任意值。类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式。前花括号 `{` 必须和 switch 关键字在同一行。
您可以同时测试多个可能符合条件的值,使用逗号分割它们,例如:`case val1, val2, val3`
每一个 `case` 分支都是唯一的,从上直下逐一测试,直到匹配为止。
一旦成功地匹配到每个分支,在执行完相应代码后就会退出整个 switch 代码块,也就是说您不需要特别使用 `break` 语句来表示结束。
因此,程序也不会自动地去执行下一个分支的代码。如果在执行完每个分支的代码后,还希望继续执行后续分支的代码,可以使用 `fallthrough` 关键字来达到目的。
因此:
```
switch i {
case 0: // 空分支,只有当 i == 0 时才会进入分支
case 1:
f() // 当 i == 0 时函数不会被调用
}
```
并且:
```
switch i {
case 0: fallthrough
case 1:
f() // 当 i == 0 时函数也会被调用
}
```
`case ...:` 语句之后,您不需要使用花括号将多行语句括起来,但您可以在分支中进行任意形式的编码。当代码块只有一行时,可以直接放置在 `case` 语句之后。
您同样可以使用 `return` 语句来提前结束代码块的执行。当您在 switch 语句块中使用 `return` 语句,并且您的函数是有返回值的,您还需要在 switch 之后添加相应的 `return` 语句以确保函数始终会返回。
可选的 `default` 分支可以出现在任何顺序,但最好将它放在最后。它的作用类似与 `if-else` 语句中的 `else`,表示不符合任何已给出条件时,执行相关语句。
Listing 5.4 [switch1.go](examples/chapter_5/switch1.go)
```
package main
import "fmt"
func main() {
var num1 int = 100
switch num1 {
case 98, 99:
fmt.Println("It's equal to 98")
case 100:
fmt.Println("It's equal to 100")
default:
fmt.Println("It's not equal to 98 or 100")
}
}
```
输出:
Output: "It's equal to 100"
在第 12.1 节,我们会使用 switch 语句判断从键盘输入的字符(详见第 12.2 节的 switch.go。switch 语句的第二种形式是不提供任何被判断的值(实际上默认为判断是否为 true然后在每个 case 分支中进行测试不同的条件。当任一分支的测试结果为 true 时,该分支的代码会被执行。这看起来非常像链式的 `if-else` 语句,但是在测试条件非常多的情况下,提供了可读性更好的书写方式。
```
switch {
case condition1:
...
case condition2:
...
default:
...
}
```
例如:
```
switch {
case i < 0:
f1()
case i == 0:
f2()
case i > 0:
f3()
}
```
任何支持进行相等判断的类型都可以作为测试表达式的条件,包括 int、string、指针等。
Listing 5.4 [switch2.go](examples/chapter_5/switch2.go)
```
package main
import "fmt"
func main() {
var num1 int = 7
switch {
case num1 < 0:
fmt.Println("Number is negative")
case num1 > 0 && num1 < 10:
fmt.Println("Number is between 0 and 10")
default:
fmt.Println("Number is 10 or greater")
}
}
```
输出:
Output: Number is between 0 and 10
switch 语句的第三种形式是包含一个初始化语句:
```
switch initialization {
case val1:
...
case val2:
...
default:
...
}
```
这种形式可以非常优雅地进行条件判断:
```
switch result := calculate(); {
case result < 0:
...
case result > 0:
...
default:
// 0
}
```
在下面这个代码片段中,变量 a 和 b 被平行初始化,然后作为判断条件:
```
switch a, b := x[i], y[j]; {
case a < b: t = -1
case a == b: t = 0
case a > b: t = 1
}
```
switch 语句还可以被用于 type-switch详见第 11.4 节)来判断某个 interface 变量中实际存储的变量类型。
**问题 5.1**
请说出下面代码片段输出的结果:
```
k := 6
switch k {
case 4: fmt.Println("was <= 4"); fallthrough;
case 5: fmt.Println("was <= 5"); fallthrough;
case 6: fmt.Println("was <= 6"); fallthrough;
case 7: fmt.Println("was <= 7"); fallthrough;
case 8: fmt.Println("was <= 8"); fallthrough;
default: fmt.Println("default case")
}
```
**练习 5.2** [season.go](exercises/chapter_5/season.go)
写一个 Season 函数,要求接受一个代表月份的数字,然后返回所代表月份所在季节的名称(不用考虑月份的日期)。
## 链接
- [目录](directory.md)
- 上一节:[测试多返回值函数的错误](05.2.md)
- 下一节:[for 结构](05.4.md)