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
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) } }
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:
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") } }
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:
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)) } }
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:
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) } } }
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:
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") } }
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.
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") }
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.
20 + 6 = 26 20 - 6 = 14 20 * 6 = 120 20 / 6 = 3
for.