control-flujo-switch-go

Switch in Go: Multiple Cases, Logical Expressions, and Conditionless Variants

  • 4 min

A switch in Go is a selection structure for choosing between several possible cases without chaining an endless series of if else.

If you come from languages like C, C++, Java, or C#, you probably have a love-hate relationship with the switch statement. It’s useful, yes, but it has a famous trap: if you forget to put a break at the end of a case, execution “falls through” to the next case, causing bugs that are sometimes hard to detect.

In Go, the switch avoids that implicit fallthrough and also allows you to group values, evaluate conditions, and declare an auxiliary variable.

The Basic switch

Let’s start with the most important difference. In Go, break is implicit.

When Go finds a matching case, it executes the code in that block and automatically exits the switch. You don’t need to write break in each case.

package main

import "fmt"

func main() {
    day := "Monday"

    switch day {
    case "Monday":
        fmt.Println("Cheer up, the week begins!")
        // There's an automatic 'break' here. It doesn't continue executing.
    case "Friday":
        fmt.Println("It's almost the weekend!")
    default:
        fmt.Println("Just a normal day...")
    }
}
Copied!

This simple design decision eliminates one of the most common sources of errors in the history of C/C++ programming.

Multiple Cases (Lists)

What if we want to execute the same code for several values? In other languages, you’d have to stack case on top of each other. In Go, you simply separate them with commas.

func main() {
    letter := 'e'

    switch letter {
    case 'a', 'e', 'i', 'o', 'u': // Much cleaner!
        fmt.Println("It's a vowel")
    default:
        fmt.Println("It's a consonant")
    }
}
Copied!

switch Without an Expression

Another useful difference: if you omit the variable after switch, Go assumes you are evaluating true.

This turns the switch into a cleaner alternative to a long chain of if, else if, and else.

With if-else (Noisy):

t := 15
if t < 10 {
    fmt.Println("Cold")
} else if t >= 10 && t < 25 {
    fmt.Println("Warm")
} else {
    fmt.Println("Hot")
}
Copied!

With switch (Elegant):

t := 15
switch { // Equivalent to 'switch true'
case t < 10:
    fmt.Println("Cold")
case t >= 10 && t < 25:
    fmt.Println("Warm")
default:
    fmt.Println("Hot")
}
Copied!

This form is the idiomatic way in Go to replace complex chains of conditionals. It’s more readable because it aligns the conditions vertically.

Short Initialization

Just like we saw with the if, the switch supports a short initialization statement. We can execute a function, get a value, and evaluate it, limiting the scope of the variable.

package main

import (
    "fmt"
    "time"
)

func main() {
    // Declare 'today' inside the switch itself
    switch today := time.Now().Weekday(); today {
    case time.Saturday, time.Sunday:
        fmt.Println("It's the weekend, rest up.")
    default:
        fmt.Println("Time to work, today is", today)
    }

    // 'today' no longer exists here. The scope is clean.
}
Copied!

fallthrough: Continue with the Next Case

What if, for some strange reason, you need execution to continue to the next case (C’s default behavior)?

Go allows you to do this, but it forces you to be explicit by using the keyword fallthrough.

n := 1

switch n {
case 1:
    fmt.Println("One")
    fallthrough // Forces entry into the next case WITHOUT checking the condition
case 2:
    fmt.Println("Two")
}
// Output:
// One
// Two
Copied!

The use of fallthrough is very uncommon in Go. If you find yourself using it a lot, you should probably rethink your code’s logic.

Also, be careful: fallthrough jumps to the next case without evaluating its condition.

Differences from the Classic switch

These are the main differences compared to the C or C++ switch:

FeatureC / C++ / JavaGo
BreakRequired (manual)Automatic (implicit)
FallthroughDefault (dangerous)Explicit (safe)
ExpressionsConstants onlyAny valid expression
Multiple casesStacking case:Commas case 1, 2:
Without conditionNot allowedYes (replaces if-else)