Hi, I’m @Luo Zhu

This article was first published on luo Zhu’s official website

This article was translated from Golang Tutorial Series

This article synchronizes in the public account “luo Zhu early teahouse”, reprint please contact the author.

What is a switch statement?

Switch is a conditional statement that evaluates an expression and compares it to a list of possible matches, and executes the appropriate block of code. Think of it as an idiomatic way to replace complex if statements.

The sample

Talk is cheap,show you the example. Let’s start with a simple example that takes a finger number as input and outputs the name of that finger. For example, 1 is thumb, 2 is index finger, and so on.

package main

import (
    "fmt"
)

func main(a) {
    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")}}Copy the code

Run in playground

In the program Switch Finger in line 10 above, compare the value of finger to each case statement. Judge the condition from top to bottom and execute the first branch that matches the expression. In this case, finger has a value of 4, so the output is:

Finger 4 is Ring
Copy the code

Duplicate branches are not allowed

It is not allowed to reuse branches with the same constant value. / Prog. Go :19:7: Duplicate Case 4 in switch previous case at./prog. Go :17:7

package main

import (
    "fmt"
)

func main(a) {
    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 branches
        fmt.Println("Another Ring")
    case 5:
        fmt.Println("Pinky")}}Copy the code

Run in playground

The default branch

We only have five fingers. What happens if you enter an incorrect finger number? We need a default branch. When all else does not match, the default branch is executed.

package main

import (
    "fmt"
)

func main(a) {
    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 branch
        fmt.Println("incorrect finger number")}}Copy the code

Run in playground

In the program above, finger is 8, which doesn’t match anything, so an Incorrect Finger number is printed by default. It is unnecessary to use default as the last branch of the switch statement. It can exist anywhere in the Switch.

You may also notice a slight change in the Finger statement. It is declared in the switch statement. The switch can contain optional statements that are executed before the expression is evaluated. In line 8, you declare finger first and then use it in the expression. In this case, the scope of finger is limited to the switch module.

Multiexpression branching

Multiple expressions can be contained by separating them with commas.

package main

import (
    "fmt"
)

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

Run in playground

The program above determines if letter is a vowel. The code in line 11 case “a”, “e”, “I “, “o”, “u”: matches any vowel. Since I is a vowel, the program prints:

Letter i is a vowel
Copy the code

Expressionless branching

Expressions in switch are optional and can be omitted. If the expression is omitted, the switch is considered to be Switch true and each case expression is evaluated and the corresponding code block is executed.

package main

import (
    "fmt"
)

func main(a) {
    num := 75
    switch { // The 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)
    }

}
Copy the code

Run in playground

In the above program, there is no expression in the switch, so consider it true and judge each case. Case num> = 51 && num <= 100: true

75 is greater than 51 and less than 100
Copy the code

This type of switch can be thought of as an alternative to multiple if else statements.

Fallthrough

In Go, control is released from the Switch statement immediately after the branch is executed. The fallthrough statement is used to transfer control to the first statement of the branch that occurs immediately after the branch executes.

Let’s write a program to understand Fallthrough. Our program will check if the number entered is less than 50, 100, or 200. For example, if you type 75, the program prints 75 less than 100 and 200. We’ll use Fallthrough to do this.

package main

import (
    "fmt"
)

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

func main(a) {
    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)
    }
}
Copy the code

Run in playground

Switch and case expressions can only be constants. They can also be evaluated at run time. In the above program, num on line 14 is initialized as the return value of the function number(). Control resides within the switch and makes judgments about branches. Case num <100 in line 18: correct, the program will print 75 is lesser than 100. The next statement is fallthrough. When fallthrough is encountered, control moves to the first statement in the next case and prints 75 is Lesser than 200. The output of this program is:

75 is lesser than 100
75 is lesser than 200
Copy the code

Fallthrough should be the last statement in case. If it is somewhere in the middle, the compiler will report an error fallthrough statement out of place.

Fallthrough occurs even if the branch is computed to be false

There are some nuances to consider when using fallthrough. Fallthrough occurs even if the branch is computed to be false.

Consider the following procedure.

package main

import (
    "fmt"
)

func main(a) {
    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)
    }
}
Copy the code

Run in playground

In the above program, num is 25, less than 50, so the case on line 9 is true. Line 11 shows fallthrough. Case num> 100: Since num < 100, 12 is false. But Fallthrough doesn’t take that into account. Fallthrough occurs even if the branch is computed to be false.

The above program will print:

25 is lesser than 50
25 is greater than 100
Copy the code

Therefore, make sure you understand what to do with Fallthrough.

One more thing is that you cannot use fallthrough in the last branch of the Switch. If a fallthrough exists in the last case, the following compilation error will result.

cannot fallthrough final case in switch
Copy the code

The switch of the switch

You can use the break statement to terminate the switch before it is complete. Let’s change the above example to an artificial one to see how break works.

Let’s add a condition that if num is less than 0, the switch should terminate.

package main

import (
    "fmt"
)

func main(a) {
    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)
    }
}
Copy the code

Run in playground

In the above program, num is -5. When the control weight reaches the if statement on line 10, the condition is satisfied because num <0. The break statement terminates before the switch completes, and the program prints nothing.

Exit the external loop

When the switch case is inside the for loop, you may need to terminate the for loop as early as possible. This can be done by marking the for loop and breaking the for loop with that tag inside the switch statement. Let’s look at an example.

Let’s write a program to generate a random even number.

We will create an infinite for loop and use the switch condition to determine whether the generated random number is even. If it is even, the resulting number is printed and its label is used to terminate the for loop. The Intn function of the RAND package is used to generate non-negative pseudo-random numbers.

package main

import (
    "fmt"
    "math/rand"
)

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

}
Copy the code

Run in playground

In the program above, the for loop in line 9 is marked randloop. Use the Intn function on line 11 to generate a random number between 0 and 99 (not including 100). If an even number is generated, the loop is broken at line 14 using the tag.

The program prints:

Generated even number 18
Copy the code

Note that if you use an unlabeled break statement, only the switch statement is broken and the loop continues. Therefore, marking the loop and using it in a break statement inside the switch is necessary to break the external for loop.