Break in Go: Does it break switch and select? Comparison of approaches

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Break that confuses: how Go flipped the familiar "switch rule"

\n\n

If you've ever written code in C, C++, Java, or JavaScript, you know the ritual: after each case in a switch, you must put a break. Otherwise — welcome to the hell of "fall-through", where code executes from one case to another until it encounters a break or the end of the construct.

\n\n

Now imagine: you switch to Go, write a switch, and out of habit put a break at the end of each case. The code works. But you start wondering: "Is it even needed? And what happens if I remove it?".

\n\n

This question is one of the most popular on Stack Overflow in the Go section. And the answer surprises beginners: in Go, break in switch and select is not mandatory, but it exists and does something different. Let's figure it out with examples so you never get confused again.

\n\n

Go vs. C: "inverted" switch

\n\n

In classic C-like languages, switch works like this:

\n\n
// Pseudo-C code\nint x = 2;\nswitch(x) {\n    case 1:\n        printf("One");\n        break;  // Without break — will fall through to the next case\n    case 2:\n        printf("Two");\n        break;\n    default:\n        printf("Other");\n}\n// Output: "Two"
\n\n

Remove the break after case 1 — and the program will print "OneTwo". This behavior is called fall-through, and it often leads to bugs.

\n\n

In Go, they decided: "Enough of that!" By default, each case in a switch automatically terminates, and break is not needed:

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    x := 2\n    switch x {\n    case 1:\n        fmt.Println("One")\n        // break not needed — we'll exit the switch\n    case 2:\n        fmt.Println("Two")\n        // break not needed\n    default:\n        fmt.Println("Other")\n    }\n    // Output: "Two"\n}
\n\n

But if you still put a break — nothing bad happens, the code will just exit the switch earlier. However, why add an unnecessary break if this is the default behavior?.

\n\n

What about fall-through?

\n\n

If you need to "fall through" to the next case, Go provides an explicit keyword — fallthrough:

\n\n
switch x {\ncase 1:\n    fmt.Println("One")\n    fallthrough  // Explicitly saying: "I want to go to the next case"\ncase 2:\n    fmt.Println("Two")\ndefault:\n    fmt.Println("Other")\n}\n// When x=1 it will output: "One" and "Two"
\n\n

Note: fallthrough only works for the next case and not as a chain. This is done intentionally to avoid accidental errors.

\n\n

Select: the multi-channel "brother" of switch

\n\n

Go has a unique construct — select. It resembles switch but only works with channels. And here break also exists, but with a twist.

\n\n
package main\n\nimport (\n    "fmt"\n    "time"\n)\n\nfunc main() {\n    ch1 := make(chan string)\n    ch2 := make(chan string)\n\n    go func() {\n        time.Sleep(1 * time.Second)\n        ch1 <- "Hello from channel 1"\n    }()\n    go func() {\n        time.Sleep(2 * time.Second)\n        ch2 <- "Hello from channel 2"\n    }()\n\n    select {\n    case msg1 := <-ch1:\n        fmt.Println(msg1)\n        break  // Exit from select\n    case msg2 := <-ch2:\n        fmt.Println(msg2)\n        break  // Exit from select\n    case <-time.After(3 * time.Second):\n        fmt.Println("Timeout")\n    }\n}
\n\n

Here break is also not mandatory — select terminates after executing one case. But why is it needed? The answer: to break out of an outer loop!

\n\n

The main "feature" of br

Blogs

Book Recommendations