第十篇 Switch 语句
欢迎来到Golang教程系列的第十篇
什么是switch语句
switch是条件语句,判断一个表达式,比较列出的所有可能的匹配值,然后执行相关的代码块。可以考虑用这个来代替复杂的if else从句。
例子
一个好的例子比说一百句话都管用,让我们写一个简单例子。就输入一个手指数,然后输出这个手指的名称,例如,1是拇指,2是食指,诸如此类。
package main
import (
"fmt"
)
func main() {
finger := 4
fmt.Printf("Finger %d is ", 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,所以会打印出
Finger 4 is 无名指
重复的case是不允许的
有多个重复值的case是不允许的,如果你尝试运行下面的程序,编译器就会报错./main.go:20:7: duplicate case 4 in switch previous case at ./main.go:18:7
package main
import (
"fmt"
)
func main() {
finger := 4
fmt.Printf("Finger %d is ", 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("小指")
}
}
默认case
我们一只手只有五个手指,如果我们输入了一个错误的手指数会怎么样呢?这时候默认(defult)就闪亮登场了,默认case会在其它case没有匹配的时候执行。
package main
import (
"fmt"
)
func main() {
switch finger := 8; finger {
case 1:
fmt.Println("拇指")
case 2:
fmt.Println("食指")
case 3:
fmt.Println("中指")
case 4:
fmt.Println("无名指")
case 5:
fmt.Println("小指")
default: //默认case
fmt.Println("错误的手指数")
}
}
上面的程序中,finger为8,并没有匹配任何的case,所以会打印出错误的手指数,defaultcase并没有要求说要放在switch语句的最后面,它可以放在switch的任何地方。
你可能也留意到了关于声明finger有个小改变,它是在switch语句中声明。在执行判断表达式之前,switch还包含一个可选的语句。上面的例子中,finger首先声明,然后才执行表达式,finger的作用范围是在switch模块内。
case里面多个表达式
在一个case里面可以放多个表达式,只需用逗号隔开。
package main
import (
"fmt"
)
func main() {
letter := "i"
fmt.Printf("Letter %s is a ", letter)
switch letter {
case "a", "e", "i", "o", "u": //case里有多个表达式
fmt.Println("vowel")
default:
fmt.Println("not a vowel")
}
}
上面的程序判断letter是不是元音字母(vowel),case "a", "e", "i", "o", "u":匹配了所有的元音字母,因为i是一个元音字母,所有程序将会输出
Letter i is a vowel
无表达式的switch
表达式在switch中是可选的,可以省略的。如果省略了表达式,那么switch就会默认为switch true,然后判断每个case表达式是否为truth,然后执行相关的代码块。
package main
import (
"fmt"
)
func main() {
num := 75
switch { //省略了表达式
case num >= 0 && num <= 50:
fmt.Printf("%d大于0,小于50", num)
case num >= 50 && num <= 100:
fmt.Printf("%d大于51,小于100",num)
case num >= 101:
fmt.Printf("%d大于100",num)
}
}
上面的程序中,switch是省略了的,因此默认为true,并且判断case表达式是否为true。而num >= 50 && num <= 100:是true,所以程序会输出:
75大于51,小于100
这个类型的switch可以考虑用来代替多个if else从句。
Fallthrough 失败?
在Go中,一个case语句执行以后,会马上跳出switch语句。fallthrough语句可以传输控制当一个case执行后,紧接着执行下一个的case。
让我们写一个程序来了解下fallthrough。我们的程序会检查输入数字是否小于50,100,200。例如,如果我们输入75,那么程序就会打印100和200,我们将通过fallthrough来实现。
package main
import (
"fmt"
)
func number() int {
num := 15 * 5
return num
}
func main() {
switch num := number(); { // num不是一个常量
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",num)
}
}
switch和case表达式不一定是要常量,它们也可以在运行时求值。在上面的程序中,num初始值为函数number()的返回值。控制流来到case num < 100:判断为true,所以程序会执行输出75小于100,下一个语句是fallthrough。当遇到fallthrough时,控制流会转移到紧接着的下一个case语句,并打印出75小于200。下面是程序的输出。
75小于100
75小于200
fallthrough应该放在case语句的最后面,如果放在了其它地方,编译器就会报错fallthrough statement out of place
当Fallthrough遇到case判断失败时
使用fallthrough时还有一个需要考虑的,就是执行的下一个case,即使case表达式是false的,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, 因此case num < 50计算值为true,接着出现fallthrough。转而执行下一个case,表达式为case num > 100:,因为num<100,所以值为false。 但是fallthrough不考虑这个,即使它的下一个case为false也会执行。
上面的程序会输出
25 is lesser than 50
25 is greater than 100
所以你要确保自己知道fallthrough用在哪个场景。
还有一点是,fallthrough不能放在switch的最后一个case,因为在这之后,没有其它的case了,倘若你这样做了,那将会编译报错。
cannot fallthrough final case in switch
Breaking switch
break可以用来在switch自己完成之前提前终止它。让我们修改下上面的程序,理解下break是怎么工作的。
让我们添加一个条件判断num小于0,然后终止switch。
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\n",num)
}
}
在上面的程序中,num为-5,当运行控制到if num < 0语句时,条件语句满足num < 0,break语句会在自动完成之前提前终止,不会再打印任何东西。
Breaking 外层loop循环
当switch语句放在一个for循环里面时,有可能需要会需要提前终止for循环.我们可以通过for循环标记来实现,breaking for循环需要把标记放在switch语句里面。让我们来看下例子。
我们要写一个生成随机数的程序。
我们会先生成一个无限的for循环,然后用switch case判断生成的随机数是否为偶数,如果是偶数,那就打印出生成的数字,并且使用标记终止for循环。intn函数和rand包是用来生成非负的伪随机数。
package main
import (
"fmt"
"math/rand"
)
func main() {
randloop:
for {
switch i := rand.Intn(100); {
case i%2 == 0:
fmt.Printf("Generated even num %d", i)
break randloop
}
}
}
在上面的程序中,for循环的标记为randloop,使用Intn函数生成从0到99的随机数。如果生成的随机数是偶数,那么就会使用标记(label)来终止程序。
上面程序会打印
Generated even num 18
请注意,如果使用break语句时没有带上标记label,那只会break switch语句,for循环还会继续运行。所以要break外层for循环时,标记循环并且在switch内部break标记是必不可少的。
以上就是本篇的全部,感谢阅读,这是我第一次翻译,难免会有翻译不当的地方,如果有什么反馈和评论,欢迎提出来!
浙公网安备 33010602011771号