Switch语句
Q7nl1s admin

什么是 switch 语句?

switch 是一个条件语句,它计算表达式并将其与可能匹配的列表进行比较并执行相应的代码块。它可以被认为是替换复杂if else从句的惯用方式。

Example

一个示例程序好过说一百字。让我们从一个简单的示例开始,它将手指编号作为输入并输出该手指的名称:)。例如,1 是Thumb,2 是Index,依此类推。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import (
"fmt"
)

func main() {
finger := 4
fmt.Printf("Finger %d is ", finger)
switch finger {
case 1:
fmt.Println("Thumb")
case 2:
fmt.Println("Index")
case 3:
fmt.Println("Middle")
case 4:
fmt.Println("Ring")
case 5:
fmt.Println("Pinky")

}
}

在上述程序switch finger中的第 10 行比较finger每个case语句的值。从上到下对案例进行评估,并执行与表达式匹配的第一个案例。在这种情况下,finger有一个值4,因此输出:

1
Finger 4 is Ring  

重复的case不被允许

不允许出现具有相同常数值的重复case。如果你尝试运行下面的程序,编译器会报下列错

./prog.go:19:7: duplicate case 4 in switch previous case at ./prog.go:17:7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import (
"fmt"
)

func main() {
finger := 4
fmt.Printf("Finger %d is ", finger)
switch finger {
case 1:
fmt.Println("Thumb")
case 2:
fmt.Println("Index")
case 3:
fmt.Println("Middle")
case 4:
fmt.Println("Ring")
case 4: //duplicate case
fmt.Println("Another Ring")
case 5:
fmt.Println("Pinky")

}
}

Default case

我们手上只有 5 根手指。如果我们输入错误的手指编号会发生什么?这是就是default出现的地方。当其他情况都不匹配时,将执行default

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"fmt"
)

func main() {
switch finger := 8; finger {
case 1:
fmt.Println("Thumb")
case 2:
fmt.Println("Index")
case 3:
fmt.Println("Middle")
case 4:
fmt.Println("Ring")
case 5:
fmt.Println("Pinky")
default: //default case
fmt.Println("incorrect finger number")
}
}

在上面的程序中finger8,它与任何情况都不匹配,因此在default下打印incorrect finger number。没有必要将default作为 switch 语句中的最后一种情况。它可以出现在switch中的6任何位置。

您可能还注意到finger. 它在 switch 中声明。switch 可以包含一个可选语句,该语句在计算表达式之前执行。在第8行finger先声明再在表达式中使用。在这种情况下,finger的作用域仅限于 switch 块。

一个case中有多个常量表达式

通过用逗号分隔多个表达式,可以在一个 case 中包含多个表达式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import (
"fmt"
)

func main() {
letter := "i"
fmt.Printf("Letter %s is a ", letter)
switch letter {
case "a", "e", "i", "o", "u": //multiple expressions in case
fmt.Println("vowel")
default:
fmt.Println("not a vowel")
}
}

上面的程序判断letter是否是元音。11行中的代码case "a", "e", "i", "o", "u": 匹配任何元音。因为i是元音,所以这个程序打印:

1
Letter i is a vowel  

Expressionless switch

switch 中的表达式是可选的,可以省略。如果表达式被省略,则开关被认为是switch true,并且每个case表达式都被评估为真,并执行相应的代码块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import (
"fmt"
)

func main() {
num := 75
switch { // expression is omitted
case num >= 0 && num <= 50:
fmt.Printf("%d is greater than 0 and less than 50", num)
case num >= 51 && num <= 100:
fmt.Printf("%d is greater than 51 and less than 100", num)
case num >= 101:
fmt.Printf("%d is greater than 100", num)
}

}

在上面的程序中,switch 中没有表达式,因此它被认为是 true,并且每个 case 都被评估。第12行case num >= 51 && num <= 100:true,程序打印:

1
75 is greater than 51 and less than 100  

这种类型的 switch 可以被认为是多个if else子句的替代方案。

Fallthrough

在 Go 中,一个 case 执行后立即脱离 switch 语句。fallthrough语句用于将控制转移到在已执行的案例之后相邻出现案例的第一条语句。

让我们编写一个程序来理解fallthrough。我们的程序将检查输入的数字是否小于 50、100 或 200。例如,如果我们输入 75,程序将打印 75 小于 100 和 200。我们将使用fallthrough.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import (
"fmt"
)

func number() int {
num := 15 * 5
return num
}

func main() {

switch num := number(); { //num is not a constant
case num < 50:
fmt.Printf("%d is lesser than 50\n", num)
fallthrough
case num < 100:
fmt.Printf("%d is lesser than 100\n", num)
fallthrough
case num < 200:
fmt.Printf("%d is lesser than 200", num)
}

}

Switch 和 case 表达式不必只是常量。它们也可以在运行时进行评估。在上面的程序中num在第 14 行中被初始化为函数行号 18的返回值number()。控制进入switch内部并评估每条case。第 18 行的case num < 100: 语句为真,程序打印75 is lesser than 100。下一条语句是fallthrough。当fallthrough遇到时,控件移动到下一个案例的第一条语句并打印75 is lesser than 200。程序的输出是

1
2
75 is lesser than 100  
75 is lesser than 200

fallthrough应该是case中的最后一条语句。如果它出现在中间的某个地方,编译器会报错fallthrough statement out of place.

当case为false的时候Fallthrough也会继续生效

使用fallthrough时需要考虑一个微妙之处。即使case评估为假,Fallthrough也会继续生效。

请考虑以下程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import (
"fmt"
)

func main() {
switch num := 25; {
case num < 50:
fmt.Printf("%d is lesser than 50\n", num)
fallthrough
case num > 100:
fmt.Printf("%d is greater than 100\n", num)
}

}

在上面的程序中,num是 25,它小于 50,因此第 9 行评估为真。fallthrough出现在第 11 行中。12行号中的下一个案例case num > 100:是错误的,因为 num < 100。但是 fallthrough 没有考虑到这一点。即使案例评估为假,Fallthrough也会继续生效。

上面的程序将打印:

1
2
25 is lesser than 50  
25 is greater than 100

因此,请确保您了解在使用 fallthrough 时您在做什么。

还有一件事是fallthrough不能在最后一种情况下使用 switch,因为没有更多的情况可以通过。如果fallthrough在最后一种情况下存在,则会导致以下编译错误。

1
cannot fallthrough final case in switch  

Breaking switch

break语句可用于在 switch 完成之前提前终止它。让我们将上面的示例修改为一个人为的示例,以了解 break 的工作原理。

让我们添加一个条件,如果num小于 0,则switch应该终止。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"fmt"
)

func main() {
switch num := -5; {
case num < 50:
if num < 0 {
break
}
fmt.Printf("%d is lesser than 50\n", num)
fallthrough
case num < 100:
fmt.Printf("%d is lesser than 100\n", num)
fallthrough
case num < 200:
fmt.Printf("%d is lesser than 200", num)
}

}

在上面的程序num中是-5. 当控件到达第 10 行的 if 语句时,条件满足,因为 num < 0。break 语句在 switch 完成之前终止 switch,并且程序不打印任何内容:)。

打破外部 for 循环

当 switch case 在for 循环中时,可能需要提前终止 for 循环。这可以通过label标记 for 循环并在 switch 语句中使用该标签中断 for 循环来完成。让我们看一个例子。

让我们编写一个程序来生成一个随机偶数。

我们将创建一个无限 for 循环并使用 switch case 来确定生成的随机数是否为偶数。如果是偶数,则打印生成的数字并使用其标签终止 for 循环。该rand包中函数Intn的功能用于生成非负伪随机数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import (
"fmt"
"math/rand"
)

func main() {
randloop:
for {
switch i := rand.Intn(100); {
case i%2 == 0:
fmt.Printf("Generated even number %d", i)
break randloop
}
}

}

在上面的程序中,使用标签在第 9 行标记randloop。for 循环第 11 行中的Intn函数生成一个介于 0 和 99 之间(不包括 100)的随机数。如果生成的数字是偶数,则for循环在第 14 行中断。。

该程序打印:

1
Generated even number 18  

请注意,如果使用不带标签的 break 语句,则只会中断 switch 语句,for循环将继续运行。因此,标记循环并在 switch 内的 break 语句中使用它是中断外部 for 循环的必要条件。

这将我们带到本教程的结尾。还有另一种类型的 switch 称为type switch。当我们学习接口时,我们会研究这个。

 Comments
Comment plugin failed to load
Loading comment plugin
Powered by Hexo & Theme Keep
Unique Visitor Page View