Skip to content
Theory · Conditions · lesson 4 of 7

switch

The lobby of a large building has a directory: "Accounting, 3rd floor; HR, 5th floor; cafeteria, 1st floor." You don't walk through every floor in turn. You find your line in the directory and go straight to the right floor.

An else if chain is like walking through the floors. When one variable is compared with several values, the chain repeats the same comparison in every branch. The switch statement works like the lobby directory: it evaluates the expression once and runs the case branch with the same value:

GO
package main

import "fmt"

func main() {
    day := 6
    switch day {
    case 1, 2, 3, 4, 5:
        fmt.Println("workday")
    case 6, 7:
        fmt.Println("weekend") // weekend
    default:
        fmt.Println("no such day")
    }
}

Let's walk through the program:

  1. switch day evaluates day and gets 6.
  2. case 1, 2, 3, 4, 5: these values don't match.
  3. case 6, 7: the list contains six, so the program prints weekend.
  4. default: execution never reaches this branch.

case and default branches

A switch with an expression has two kinds of branches.

case with values

A case branch lists the values for which it runs. The rules are:

  • several values of one case are listed with commas: case 6, 7:;
  • the values have the same type as the expression after switch;
  • one value cannot appear in two cases: the compiler reports duplicate case.

default

The default branch runs when no case matches. Without it, nothing runs in that case.

When a function returns from the branches of a switch, the compiler needs a default branch or a return after the switch. Without them it reports missing return, even if the conditions cover every case.

The end of a branch

In different languages a switch branch ends in different ways. Go has two options.

No break

After a branch runs, the switch ends at once, so no break is needed at the end of a branch. In C it is the other way round: without break, execution falls through into the next branch.

fallthrough

In Go you turn fall-through on explicitly, with fallthrough at the end of a branch:

GO
level := 2
switch level {
case 2:
    fmt.Print("admin ")
    fallthrough
case 1:
    fmt.Println("user") // admin user
}

Let's see what fallthrough does:

  • it moves into the next case without checking its value, so with level == 2 the program prints admin user;
  • with level == 1 the program prints only user: the case 2 branch did not run;
  • fallthrough goes last in a branch, and it is not allowed in the last branch of a switch: there is nowhere to go.

fallthrough is rarely needed: several values in one case usually do the job.

Interviewers like to ask this: how does switch in Go differ from switch in C? The core of the answer: in Go a branch never falls into the next one by itself, no break is needed, and fall-through is turned on with fallthrough.

switch without an expression

The expression after switch can be left out. Then each case holds a condition of type bool, and such a switch replaces a chain of if and else if:

GO
switch t := 25; {
case t < 0:
    fmt.Println("frost")
case t < 30:
    fmt.Println("mild") // mild
case t > 10:
    fmt.Println("warm")
}

Conditions in case

The first branch with a true condition runs. In the example the conditions t < 30 and t > 10 are both true, but the program prints only mild. Execution never reaches case t > 10.

Here the lobby directory stops being an exact picture. In a directory each department has one line, while the conditions in cases can hold for several lines at once. Then the order decides: Go reads the branches from top to bottom and runs the first one that fits.

An init statement

As with if, an init statement can follow the word switch, and the semicolon after it stays: switch t := 25; {.

  • The variable t from the init statement is visible in every branch.
  • After the switch it disappears, as with if.
  • Without an init statement you write switch {.

Common mistake

In a switch without an expression, a broad condition was placed above a narrow one:

GO
score := 95
switch {
case score >= 60: // ✗
    fmt.Println("pass")
case score >= 90:
    fmt.Println("excellent")
}

The program prints pass: the condition score >= 60 is true for 95 and is checked first. The score >= 90 branch never runs for any score. Put the strictest condition first: score >= 90, then score >= 60.

Key points

  • switch evaluates the expression once and runs the case with the same value; default runs when none matches.
  • After a branch, switch ends by itself: no break is needed, and fall-through is turned on with fallthrough.
  • A switch without an expression runs the first branch with a true condition.
  • That is why the strictest condition goes first in such a switch.

Subscribe to take the course

The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.

Sign in another way