switch 是一个条件语句,它计算表达式并将其与可能匹配的列表进行比较,然后执行相应的代码块。它可以被认为是替换复杂if else子句的惯用方式。
一个示例程序胜过一百个字。让我们从一个简单的示例开始,该示例将手指编号作为输入并输出该手指的名称:)。
例如,1 是拇指,2 是食指,依此类推。
package main
import (
"fmt"
)
func main() {
finger := 4
fmt.Printf("手指 %d 是 ", finger)
switch finger {
case 1:
fmt.Println("拇指")
case 2:
fmt.Println("食指")
case 3:
fmt.Println("中指")
case 4:
fmt.Println("无名指")
case 5:
fmt.Println("小指")
}
}
在上面的程序中switch finger,将 finger与每个case语句进行比较。从上到下计算案例,并执行第一个与表达式匹配的案例。在这种情况下,finger有一个值4,因此
手指 4 是 无名指
被打印。
不允许出现具有相同常量值的重复情况。如果你尝试运行下面的程序,编译器会报错
package main
import (
"fmt"
)
func main() {
finger := 4
fmt.Printf("手指 %d 是 ", finger)
switch finger {
case 1:
fmt.Println("拇指")
case 2:
fmt.Println("食指")
case 3:
fmt.Println("中指")
case 4:
fmt.Println("无名指")
case 4:
fmt.Println("无名指")
case 5:
fmt.Println("小指")
}
}
在上面的程序中,输出:
./prog.go:19:7: duplicate case 4 (constant of type int) in expression switch
./prog.go:17:7: previous case
我们的手上只有5根手指。如果我们输入错误的手指号码会怎样?这就是默认情况出现的地方。当其他情况都不匹配时,将执行默认情况。
package main
import (
"fmt"
)
func main() {
finger := 11
fmt.Printf("手指 %d 是 ", finger)
switch finger {
case 1:
fmt.Println("拇指")
case 2:
fmt.Println("食指")
case 3:
fmt.Println("中指")
case 4:
fmt.Println("无名指")
case 5:
fmt.Println("小指")
default:
fmt.Println("无效数字")
}
}
在上面的程序中finger,它与任何情况都不匹配,因此在默认情况下会被打印。
手指 10 是 无效数字
这不一定default是 switch 语句中的最后一个。它可以出现在任何位置。
您可能还注意到finger 的声明中的一个小变化。它是在开关本身中声明的。switch 可以包含在计算表达式之前执行的可选语句。finger先声明,后在表达式中使用。本例中的范围finger仅限于开关块。
可以在一个 case 中包含多个表达式,并用逗号分隔它们。
package main
import (
"fmt"
)
func main() {
letter := "i"
fmt.Printf("Letter %s is a ", letter)
switch letter {
case "a", "e", "i", "o", "u":
fmt.Println("vowel")
default:
fmt.Println("not a vowel")
}
}
上面的程序判断是否letter是元音。第 1 行中的代码case "a", "e", "i", "o", "u":。11 匹配任何元音。由于i是元音,因此该程序打印
Letter i is a vowel
switch 中的表达式是可选的,可以省略。如果省略表达式,则认为是 switch ,并且评估switch true每个表达式的真值并执行相应的代码块。case
package main
import (
"fmt"
)
func main() {
num := 75
switch {
case num >= 0 && num <= 50:
fmt.Printf("%d 0-50之间", num)
case num >= 51 && num <= 100:
fmt.Printf("%d 51-100之间", num)
case num >= 101:
fmt.Printf("%d 100以上", num)
}
}
在上面的程序中,switch 中不存在表达式,因此它被视为 true,并且对每种情况进行评估。case num >= 51 && num <= 100:是true并且程序打印
75 51-100之间
这种类型的开关可以被视为多个子句的替代if else。
在 Go 中,执行 case 后立即从 switch 语句中产生控制。语句fallthrough用于将控制转移到紧随已执行的情况之后出现的情况的第一条语句。
让我们编写一个程序来理解Fallthrough。我们的程序将检查输入的数字是否小于 50、100 或 200。例如,如果我们输入 75,程序将打印 75 小于 100 和 200。我们将使用 来实现此目的fallthrough。
package main
import (
"fmt"
)
func number() int {
num := 15 * 5
return num
}
func main() {
switch num := number(); {
case num < 50:
fmt.Printf("%d 小于50 \n", num)
fallthrough
case num < 100:
fmt.Printf("%d 小于100 \n", num)
fallthrough
case num < 200:
fmt.Printf("%d 小于200 \n", num)
}
}
Switch 和 case 表达式不必只是常量。它们也可以在运行时评估。在上面的程序中num,初始化为number()第 1 行函数的返回值。case num < 100: 为真,程序打印75 小于100 。当遇到fallthrough时,控件移动到下一个情况的第一个语句并打印75 小于200 。程序的输出是
75 小于100
75 小于200
*fallthrough应该是 *case中的最后一个语句。如果它出现在中间的某个地方,编译器会报错fallthrough statement out of place.
即使case评估结果为假,也会发生失败
使用时需要考虑一下fallthrough的微妙之处。即使case评估结果为假,失败也会发生。
请考虑以下程序。
package main
import (
"fmt"
)
func main() {
switch num := 25; {
case num < 50:
fmt.Printf("%d 小于 50\n", num)
fallthrough
case num > 100:
fmt.Printf("%d 大于 100\n", num)
}
}
在上面的程序中,num是 25,小于 50,因此是第 1 行的情况。评估结果为 true。fallthrough出现在第 1 行。
case num > 100,下一个case是false,因为 num < 100。但 Fallthrough 不考虑这一点。即使case评估结果为假,也会发生失败。
上面的程序将打印
25 is lesser than 50
25 is greater than 100
因此,请确保您了解使用 Fallthrough 时在做什么。
还有一件事是fallthrough不能在switch的语句最后一种情况下使用,因为没有更多的情况可以失败。如果fallthrough出现在最后一种情况下,将会导致以下编译错误。
cannot fallthrough final case in switch
该break语句可用于在 switch 完成之前提前终止它。让我们将上面的示例修改为一个人为的示例,以了解break 是如何工作的。
让我们添加一个条件,如果num小于 0,则开关应终止。
package main
import (
"fmt"
)
func main() {
switch num := -5; {
case num < 50:
if num < 0 {
break
}
fmt.Printf("%d 小于 50\n", num)
fallthrough
case num < 100:
fmt.Printf("%d 小于 100\n", num)
fallthrough
case num < 200:
fmt.Printf("%d 小于 200", num)
}
}
上面的程序中num是-5.当程序到达if 语句时由于 num < 0,所以满足条件。break 语句在 switch 完成之前终止 switch,并且程序不会打印任何内容。
当 switch case 位于for循环内时,可能需要提前终止 for 循环。这可以通过标记 for 循环并在 switch 语句内使用该标签中断 for 循环来完成。
让我们看一个例子。我们编写一个程序来生成一个随机偶数。
我们将创建一个无限 for 循环,并使用 switch case 来确定生成的随机数是否为偶数。如果是偶数,则打印生成的数字并使用其标签终止 for 循环。
package main
import (
"fmt"
"math/rand"
)
func main() {
randloop:
for {
switch i := rand.Intn(100); {
case i%2 == 0:
fmt.Printf("生成的偶数 %d", i)
break randloop
}
}
}
在上面的程序中,for 循环被标记randloop在第 1 行。 rand.Intn(100)的函数生成 0 到 99 之间的随机数(不包括 100) 。如果生成的数字是偶数,则使用标签进行中断。
该程序打印,
生成的偶数 96
请注意,如果使用不带标签的break语句,则只会中断switch语句,而循环将继续运行。因此,标记循环并在 switch 内的 Break 语句中使用它,对于中断外部 for 循环是必要的。