# switch语句

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

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

```go
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在线运行](https://play.golang.org/p/afW0YmM3yXF) 该程序中`switch finger`语句将`finger`的值跟每一个`case`值从前到后依次去比较，匹配上会执行对应的代码块。由于`switch finger`语句执行时`finger`值为4，因此`case 4`对应的代码块得以执行，打印出`Ring`。

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

```go
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在线运行](https://play.golang.org/p/ibBwPF60t9Q)

#### 兜底case

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

```go
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在线运行](https://play.golang.org/p/Q4CYU9j4bZX) 这里由于`finger`值为8，无法匹配到任何一个`case`值，因此会执行兜底case的代码块，打印出`incorrect finger number`。

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

#### case合并

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

```go
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在线运行](https://play.golang.org/p/R5_TncSPs1A) 该程序判断`letter`变量是否是元音字母，`case "a", "e", "i", "o", "u"`语句将多种情况(所有元音字母)合并成了一条`case`语句。

#### `switch true`

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

```go
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在线运行](https://play.golang.org/p/BCQMYYMr3QJ) 该程序中`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`。

```go
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在线运行](https://play.golang.org/p/rViLL17s6Ze) 该程序中`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`语句，我们后面介绍接口时再讨论。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sunwenfei.gitbook.io/sunwenfei/golang/golang-ji-chu-jiao-cheng/tiao-jian-xun-huan/switch-yu-ju.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
