switch语句

switch语句是条件语句的一种。switch语句先计算一个表达式的值,然后将计算出来的值跟一列可能值进行比较,匹配到哪种情况就执行哪个代码块。switch语句可以等价于多个if else语句。

也许举个例子更加容易理解,下面我们写一个程序,根据数字输出对应的手指名称。比如1表示大拇指,2表示食指。

package main

import "fmt"

func main() {  
    finger := 4
    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")

    }
}

Go Playground在线运行 该程序中switch finger语句将finger的值跟每一个case值从前到后依次去比较,匹配上会执行对应的代码块。由于switch finger语句执行时finger值为4,因此case 4对应的代码块得以执行,打印出Ring

switch语句中case值不允许重复,例如下面的程序有两个case值均为4,会报错:

package main

import "fmt"

func main() {  
    finger := 4
    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")

    }
}

Go Playground在线运行

兜底case

前面程序中用手指做例子来说明switch语句用法。我们一只手上只有5个手指,因此可以匹配到数字1到5。那如果前面给finger赋值为其他错误的值,比如6,怎么办?这时兜底case就派上用场了。

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")
    }
}

Go Playground在线运行 这里由于finger值为8,无法匹配到任何一个case值,因此会执行兜底case的代码块,打印出incorrect finger number

细心的话你会注意到,我们将finger的初始化置于了switch语句内。这点跟if else语句类似,均支持这种用法。这种方式初始化finger值,finger仅在switch语句内部可见。

case合并

如果要执行的代码块相同,我们可以将多个case合并成一条语句。比如下面判断元音字母的程序:

package main

import "fmt"

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

Go Playground在线运行 该程序判断letter变量是否是元音字母,case "a", "e", "i", "o", "u"语句将多种情况(所有元音字母)合并成了一条case语句。

switch true

如果要执行的switch语句为switch true,则可简写将表达式true省去。注意这时case值都是跟true比较。

package main

import "fmt"

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

Go Playground在线运行 该程序中num值为75,case num >= 51 && num <= 100判断通过,因此打印num is greater than 51 and less than 100。其实我们简单思考下就应该知道,这种用法完全可用if else语句替换。

fallthrough

细心的话就会发现,Golang中的case语句跟JavaScript等其他编程语言不同,不需要break语句即可在执行完匹配上的代码块后立即退出整个switch语句。那么如果希望继续判断并匹配后序的case语句怎么实现呢?也有办法,就是用fallthrough

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)
    }
}

Go Playground在线运行 该程序中num值为75,因此case num < 100判断通过,执行对应的代码块,由于使用了falltrough,因此执行流程向后贯穿,接着去匹配其他的case。由于case num < 200也判断通过,因此也执行对应的代码块。该程序输出如下:

75 is lesser than 100
75 is lesser than 200

有过其他编程语言经验的人都应该知道,我们大部分情况下都会使用switch语句的break来退出switch语句,因此Golang的设计更加优雅。从这一点上也不得不说,Golang确实是取其精华,去其糟粕。

需要注意fallthrough必须在case代码块的最后执行,否则会报错。

另外还有一个type switch语句,我们后面介绍接口时再讨论。

Last updated