3.3 Make Better Choices in Go with switch

3.3 Make Better Choices in Go with switch

TL;DR

  • A switch statement is a clean way to handle multiple choices, like a tidier version of a long if-else chain.
  • It checks a single value or expression against a list of possible cases.
  • The default case is a safety net that runs if no other case matches.
  • A special "type switch" lets you check what kind of data a variable holds (e.g., text, number, etc.).

Why This Matters

Have you ever written code that feels like a giant tangled knot of if this, else if that, else if another thing...? It gets messy fast. When you have to check one variable against many possible options, this pattern becomes hard to read and even harder to fix.

The switch statement is Go's elegant solution to this problem. Think of it as a well-organized menu. Instead of asking a series of yes/no questions, you present one item (the variable) and let the program jump directly to the correct option (case). This makes your code cleaner, more readable, and less likely to hide bugs.


Concepts in Plain English

Before we dive in, let's get a few key ideas straight. They're simpler than they sound.

  • switch Statement: This is our main tool. It's like a traffic controller that looks at one car (a variable) and directs it down one of several possible roads (cases).
  • case: A specific path or option. If the variable matches the case's value, the code inside that case runs. It's like one of the destinations on a road sign.
  • default: The "none of the above" option. If the variable doesn't match any other case, the default code runs. It's the road for "all other traffic."
  • Type Switch: A special kind of switch that doesn't care about the value of a variable, but its data type. It’s like a sorting machine at a recycling plant that separates plastic, glass, and paper into different bins.

Here’s a quick reference table.

TermSimple DefinitionWhere It Shows Up
switchThe start of a choice-making block.switch myVariable { ... }
caseA single option to check against.case "admin":
defaultThe fallback option if no cases match.default:
.(type)Special syntax used only in a type switch.switch v := i.(type) { ... }

Quick Setup

You don't need to install anything to try these examples! You can run all the code snippets directly in your browser using the official Go Playground. Just copy, paste, and hit the "Run" button.


Do It Step by Step

Let's build a switch statement from the ground up. We'll cover two main scenarios: checking for a specific value and checking for a condition.

Part 1: The Basic switch for Checking Values

This is the most common use of switch. We have a variable and want to do different things based on its exact value.

Goal: Write a program that prints a message based on a user's role.

    • Input → Output:
      • If userRole is "viewer", the output is: View-only access.
      • If userRole is "admin", the output is: Full access granted.

Add a default case.This is our safety net. It runs if userRole is anything other than "admin" or "editor".

package main

import "fmt"

func main() {
    userRole := "viewer" // Try changing this to "admin" or "editor"!

    switch userRole {
    case "admin":
        // This code runs ONLY if userRole is "admin"
        fmt.Println("Full access granted.")
    case "editor":
        // This code runs ONLY if userRole is "editor"
        fmt.Println("Can write and publish content.")
    default:
        // This code runs for any other value
        fmt.Println("View-only access.")
    }
}

Add your cases.Each case represents a possible value for userRole. We'll add options for "admin" and "editor".

switch userRole {
case "admin":
    // This code runs ONLY if userRole is "admin"
    fmt.Println("Full access granted.")
case "editor":
    // This code runs ONLY if userRole is "editor"
    fmt.Println("Can write and publish content.")
}

Start with switch and the variable.We'll check a variable named userRole.

// The variable we want to check
userRole := "editor"

// Start the switch statement on that variable
switch userRole {
// ... cases go here
}
Pro Tip — In Go, you don't need to add a break at the end of each case like in some other languages. It automatically stops after a match, which prevents a lot of common bugs!

Part 2: The Conditional switch

Sometimes you don't want to check for an exact value, but for a condition (e.g., is a number greater than 100?). For this, we use a switch without a variable next to it.

Goal: Convert a numeric score into a letter grade.

    • Input → Output:
      • If score is 85, the output is: Grade: B
      • The condition score >= 90 is checked and is false.
      • The condition score >= 80 is checked and is true. This block runs, and the switch ends.

Write cases with expressions.Each case will now be a condition that results in true or false. Go will pick the first one that is true.

package main

import "fmt"

func main() {
    score := 85 // Try changing this score!

    switch {
    case score >= 90:
        // Runs if score is 90 or higher
        fmt.Println("Grade: A")
    case score >= 80:
        // Runs if score is NOT >= 90, but IS >= 80
        fmt.Println("Grade: B")
    case score >= 70:
        // Runs if score is NOT >= 80, but IS >= 70
        fmt.Println("Grade: C")
    default:
        // Runs for any score below 70
        fmt.Println("Grade: F")
    }
}

Start with a "naked" switch.This time, we just write switch followed by an opening brace {.

score := 85

// No variable here!
switch {
// ... cases with conditions go here
}

Here’s a table to help you decide which switch form to use.

Switch TypeWhen to Use ItExample
switch variable { ... }When you are checking one variable for several specific, exact values.switch httpStatus { case 200: ... case 404: ... }
switch { ... }When you need to check a series of conditions or ranges.switch { case temperature > 30: ... case temperature < 0: ... }

Examples Section

Let's look at two practical examples you might see in the wild.

Example A: Minimal Traffic Light

This is a classic switch that controls program flow based on a simple state.

package main

import "fmt"

func getActionForLight(color string) string {
    var action string
    switch color {
    case "red":
        action = "Stop"
    case "yellow":
        action = "Prepare to stop"
    case "green":
        // You can combine multiple cases!
    case "blinking green":
        action = "Go"
    default:
        action = "Unknown light color"
    }
    return action
}

func main() {
    fmt.Println("Light is red. Action:", getActionForLight("red"))
    fmt.Println("Light is green. Action:", getActionForLight("green"))
}

This code defines a function that returns a specific action string based on the traffic light's color. Notice how "green" and "blinking green" are combined into one case to produce the same result.


Example B: The "What Am I?" Type Switch

Sometimes a function receives data and doesn't know its exact type. A type switch is the perfect tool for safely figuring it out.

package main

import "fmt"

// This function accepts any kind of data
func printDetails(value interface{}) {
    fmt.Printf("The value is '%v'. ", value)

    // A type switch figures out what the actual type is
    switch v := value.(type) {
    case string:
        // Inside this case, 'v' is known to be a string
        fmt.Printf("It's a string of length %d.\n", len(v))
    case int:
        // Inside this case, 'v' is known to be an integer
        if v > 100 {
            fmt.Println("It's a large integer.")
        } else {
            fmt.Println("It's an integer.")
        }
    default:
        // For any other type
        fmt.Printf("It's a type I don't recognize: %T.\n", v)
    }
}

func main() {
    printDetails("hello")
    printDetails(42)
    printDetails(999)
    printDetails(true) // This will hit the default case
}

The interface{} type is Go's way of saying "this can be anything." The switch v := value.(type) syntax is special: it checks the type of value and also puts the correctly-typed value into a new variable v that you can use inside each case.

Here is a diagram showing how that logic flows:

flowchart LR
    subgraph Type Switch Logic
        A[Start with a variable `value`] --> B{What is the type of `value`?};
        B -->|It's a `string`| C[Run string-specific code];
        B -->|It's an `int`| D[Run integer-specific code];
        B -->|It's something else| E[Run default code];
        C --> F[End];
        D --> F[End];
        E --> F[End];
    end

ASCII Fallback: The diagram shows a variable named value entering a decision block. Based on its type (string, integer, or other), it follows a different path to execute type-specific code, after which the process concludes.


Common Pitfalls

  1. Forgetting the default case. If your variable could have an unexpected value and you don't have a default, your program might just do nothing, which can be confusing. Always add a default as a safety net.
  2. Order matters in conditional switches. In a switch { ... } block, Go runs the first case that is true and stops. If you put case score >= 70: before case score >= 90:, a score of 95 would incorrectly be graded as a "C".
  3. Mixing up case values. A switch checks for equality. case "5": (text) is not the same as case 5: (a number). This can lead to your code taking the default path when you don't expect it to.

FAQ

  • Q: Can I match multiple values in one case?
    • A: Yes! Just separate them with a comma: case "Saturday", "Sunday": fmt.Println("It's the weekend!").
  • Q: What’s the real difference between switch and a bunch of if-else statements?
    • A: Readability. For checking a single variable against many distinct values, switch is much cleaner and clearly states your intent. if-else is better for checking different, unrelated conditions.
  • Q: Does the order of cases matter?
    • A: Absolutely. Go checks them from top to bottom and stops at the first match. This is especially important for conditional switches that check ranges.
  • Q: What exactly does v := value.(type) do?
    • A: It's a special form, only for type switches. It does two things at once: 1) it checks the data type of the interface value, and 2) it creates a new variable v that has the correct, specific type, which you can then use inside the case block.

Recap

You've learned how to use switch to make your code much cleaner and more organized.

  • switch is your go-to tool for replacing messy if-else if-else chains.
  • Use a basic switch to check a variable against a list of specific values.
  • Use a conditional switch (with no variable) to check a list of boolean conditions.
  • Use a type switch to find out the data type of a variable and act on it safely.
  • Your next step? Find a messy if-else block in your code and try rewriting it as a switch!