switch

A switch picks one branch out of many. Go's switch is more flexible than C's or Java's: cases can list several values or hold any boolean condition, only the matching case runs (no accidental fall-through, no break needed), and a switch with no value replaces long if/else if chains.

Switching on a value

GO
package main

import "fmt"

func main() {
	day := "Sat"

	switch day {
	case "Mon", "Tue", "Wed", "Thu", "Fri":
		fmt.Println("Weekday: the shop opens at 9")
	case "Sat":
		fmt.Println("Saturday: the shop opens at 10")
	case "Sun":
		fmt.Println("Closed")
	default:
		fmt.Println("Unknown day:", day)
	}
}
Output
Saturday: the shop opens at 10

The cases are tried from top to bottom and the first match runs. A case can list several values separated by commas. default runs when nothing matches; it's optional and can go anywhere, though it's usually last. Duplicate constant values in cases are a compile error.

No fall-through

After a case's code runs, the switch ends — there's no need for break. If you really want to continue into the next case's body, say so with fallthrough. It skips the next case's test, so use it rarely:

GO
package main

import "fmt"

func main() {
	level := 2
	fmt.Println("Access granted to:")
	switch level {
	case 3:
		fmt.Println("  admin panel")
		fallthrough
	case 2:
		fmt.Println("  reports")
		fallthrough
	case 1:
		fmt.Println("  dashboard")
	}
}
Output
Access granted to:
  reports
  dashboard

A switch with no value

Leave out the value and each case becomes a boolean condition. This is the cleanest way to write a long chain of if/else if tests:

GO
package main

import "fmt"

func bmiCategory(bmi float64) string {
	switch {
	case bmi < 18.5:
		return "underweight"
	case bmi < 25:
		return "healthy"
	case bmi < 30:
		return "overweight"
	default:
		return "obese"
	}
}

func main() {
	for _, b := range []float64{17.2, 22.9, 27.5, 31.0} {
		fmt.Println(b, bmiCategory(b))
	}
}
Output
17.2 underweight
22.9 healthy
27.5 overweight
31 obese

A switch with a short statement

Like if, a switch can start with a short statement whose variables are scoped to the switch:

GO
package main

import (
	"fmt"
	"strings"
)

func main() {
	for _, cmd := range []string{"  START", "stop", "pause "} {
		switch c := strings.ToLower(strings.TrimSpace(cmd)); c {
		case "start":
			fmt.Println("starting")
		case "stop", "pause":
			fmt.Println("halting:", c)
		}
	}
}
Output
starting
halting: stop
halting: pause

Cases can be expressions

Case values don't have to be constants. Any expression of the right type works, evaluated top to bottom until one matches:

GO
package main

import "fmt"

func main() {
	target := 12
	guess := 3 * 4

	switch guess {
	case target - 1, target + 1:
		fmt.Println("So close!")
	case target:
		fmt.Println("Exactly right")
	default:
		fmt.Println("Keep trying")
	}
}
Output
Exactly right

break inside a switch

break inside a switch leaves the switch early. Be careful when the switch is inside a loop: a plain break leaves only the switch, not the loop. Lesson 18 shows how labels solve this.

GO
package main

import "fmt"

func main() {
	for _, n := range []int{4, -2, 0, 7} {
		switch {
		case n == 0:
			fmt.Println("zero: nothing to do")
		default:
			if n < 0 {
				fmt.Println("negative, ignoring", n)
				break // leaves the switch early
			}
			fmt.Println("processing", n)
		}
	}
	fmt.Println("loop finished")
}
Output
processing 4
negative, ignoring -2
zero: nothing to do
processing 7
loop finished

Go also has a type switch, which branches on the type of an interface value rather than its value. It's covered with interfaces in lesson 41.

Try it yourself

Write a tiny calculator that switches on the operator. Add % as another case, and a default for unknown operators.

Try it yourself · main.go
Edit the code, copy it into main.go in a new folder and run it with go run main.go (Go 1.27 or later). How to install Go
Output
20 + 6 = 26
20 - 6 = 14
20 * 6 = 120
20 / 6 = 3
Next: loops with for.