switch
switch is Go's compact alternative to a long if / else if / else chain. It takes an expression, compares it against each case, and runs the first matching branch. Unlike C and Java, cases do not fall through by default: the matched branch runs, and execution leaves the switch.
A basic switch
day := "Sat"
switch day {
case "Sat", "Sun":
fmt.Println("weekend")
case "Mon", "Tue", "Wed", "Thu", "Fri":
fmt.Println("weekday")
default:
fmt.Println("unknown day")
}
A few things to notice:
- Cases can list multiple values separated by commas.
"Sat", "Sun"means "match either". - There is no
breakat the end of each case. The break is implicit. defaultruns when no case matched. It is optional; leave it out if "unhandled value" is not a case you care about.
Cases are checked top-to-bottom and the first match wins; subsequent cases are not evaluated.
Expressionless switch
The basic switch works when you are comparing one value against a list. But a lot of real branching looks more like this:
hour := 14
if hour < 12 {
fmt.Println("morning")
} else if hour < 18 {
fmt.Println("afternoon")
} else {
fmt.Println("evening")
}
That works, but reads as a chain of independent ifs that happen to share a variable. Drop the expression after switch and the same logic gets a cleaner shape:
switch {
case hour < 12:
fmt.Println("morning")
case hour < 18:
fmt.Println("afternoon")
default:
fmt.Println("evening")
}
Each case is its own boolean expression. The first true case runs, the rest are skipped. This is the form you reach for when you are testing different conditions rather than comparing one value against a list, and it often reads cleaner than a long if / else if / else chain.
Short statement, like if
switch supports a short statement that scopes a variable to the switch block, same shape as the one you saw for if:
switch n := 10; {
case n < 0:
fmt.Println("negative")
case n == 0:
fmt.Println("zero")
default:
fmt.Println("positive")
}
// n is out of scope here
Leaving the part after the semicolon empty gives you a short-statement + expressionless combination, which is often the cleanest shape for "compute once, then branch on conditions".
switch n := 10; {
case n > 0:
fmt.Println("positive")
}
fmt.Println(n) // compile error: undefined: n
fallthrough, the opt-in version of C's default behaviour
If you genuinely want a case to continue into the next one (rare), say so explicitly with fallthrough:
switch n := 1; n {
case 1:
fmt.Println("one")
fallthrough
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
}
// prints: one, then two
fallthrough jumps to the next case unconditionally: it does NOT re-check that case's value. That is why this prints two even though n is 1. The "no fallthrough by default" rule is one of Go's quiet improvements over C; reach for fallthrough only when you really mean it.
- Three or more comparisons of one value:
switchreads better than an if/else-if chain. - Three or more unrelated boolean tests: the expressionless
switchform is still cleaner than the chain. - Two branches, one condition: stick with
if / else.switchstarts paying off once there are more branches.
The starter declares code := 404. Use an expressionless switch to print a category for the HTTP status code:
"success"ifcodeis200or201"redirect"ifcodeis301or302"client error"ifcode >= 400andcode < 500"server error"ifcode >= 500"unknown"otherwise
Each case will be a boolean expression (since the ranges cannot be written as value comparisons).
client error