Go Conditional Logic & Loops: if, switch, for Guide

Go Conditional Logic & Loops: Complete Guide
Quick Answer: Go Control Flow
Go uses if/else for decisions, switch for multi-branch logic, and a single for keyword for all loops. Unlike most languages, Go has no while, do-while, or until loops — the for keyword covers all these cases through different syntax forms. The range keyword iterates over slices, maps, strings, and channels cleanly.
Go Conditional Logic & Looping
A program without logic is just a list of instructions. To build real-world applications, you need your code to make decisions, handle errors, and process collections of data iteratively.
Go's approach to control flow is remarkably minimalist. There are no while or do-while loops. There are no parentheses around conditions. This simplicity makes Go code incredibly fast to read and difficult to hide bugs in.
Minimalist Grammar
If / Else Statements
The if statement is the most fundamental building block of logic. In Go, an if statement can also include an optional initialization statement before the condition. This is often used for error handling or scoping a variable tightly to only the if block.
The Switch Statement
Go's switch is a more powerful and safer version than what you find in C or Java. By default, Go automatically breaks at the end of each case, meaning you Don't need to write break after every block.
If you do want to fall through to the next case, you must explicitly use the fallthrough keyword.
The Only Loop: The for Loop
In Go, there is only one looping keyword: for. However, it is extremely flexible and can be used to replicate the behavior of while and do-while loops from other languages.
The Three Faces of for
for i := 0; i < 10; i++The classic three-component loop for fixed iterations.
for condition { ... }Use just a condition to loop as long as it remains true.
for { ... }An empty for block creates an infinite loop. Use 'break' to exit.
Looping Over Collections
To iterate over arrays, slices, or maps, Go provides the range keyword. It returns both the index and the value of each element.
Looping Over Maps
Ranging over a map follows the same syntax as slices, but the iteration order is not guaranteed — Go deliberately randomises map iteration to prevent developers from relying on an undefined order:
If you need to process map entries in a consistent order, extract the keys into a slice, sort it, then iterate:
Break, Continue, and Goto
Go provides three keywords for controlling loop flow:
break
Immediately exits the innermost for or switch block.
continue
Skips the rest of the current iteration and moves to the next one.
Labeled Breaks for Nested Loops
When you need to break out of multiple nested loops at once, Go supports labeled statements:
Type Switch: Go's Powerful Pattern
Go's switch has a special form called a type switch that evaluates the dynamic type of an interface value. This is commonly used when a function accepts an interface{} or any parameter:
Type switches are extensively used in JSON decoders, middleware, and any code that processes dynamic data structures.
E-E-A-T Practical Tip: Initialisation in If Statements
One of Go's most productive patterns is the if err := doSomething(); err != nil form. By combining the function call and error check into a single if statement, you scope the error variable tightly and eliminate the need for a separate variable declaration:
This is the pattern you will see in virtually every production Go codebase for error handling in functions that return multiple values.
Further Reading
For related Go fundamentals, see Go variables, types, and constants and Go functions, pointers, and structs. To apply these control flow patterns to collections, see Go slices, maps, and collections.
Next Steps
Now that you can control the flow of your program and process data in loops, we need to talk about Structure. In the next module, we will explore how to group your code into reusable Functions and how to define custom complex data types using Structs.
Common Mistakes with Go Control Flow
1. Missing break in switch — not needed
Unlike C and Java, Go switch cases do not fall through by default. Each case breaks automatically. Use fallthrough explicitly if you want fall-through behaviour. This eliminates a whole class of bugs.
2. Using for with no condition as an infinite loop
for {} is Go's infinite loop — there is no while keyword. This is intentional. Add a break or return inside the loop body to exit, or use for condition {} with a boolean expression.
3. Shadowing the loop variable in goroutines
Capture v explicitly: go func(v Item) { fmt.Println(v) }(v). The Go FAQ on loop variable capture explains this classic pitfall.
4. Using if err != nil without returning
Checking an error but continuing execution as if it did not occur is a logic bug. Every if err != nil block should either return, log and return, or explicitly handle the error before continuing.
5. Overly complex switch with many cases that should be a map
A switch with 20+ string cases mapping to fixed values is better expressed as a map[string]T lookup — it is faster, more readable, and easier to extend.
Frequently Asked Questions
Why does Go only have one loop keyword?
Go's designers deliberately kept the language small. A single for keyword covers while, do-while, and traditional for patterns with different forms of the same construct. See the Go spec on for statements.
Can I use break with a label in Go?
Yes. break Label exits the labelled outer loop or switch, which is useful for breaking out of nested loops without a boolean flag. continue Label similarly skips to the next iteration of the labelled loop.
What is the idiomatic way to iterate over a string in Go?
for i, r := range s iterates over Unicode code points (runes), not bytes. If you need byte-level iteration, use for i := 0; i < len(s); i++. The Go blog on strings covers the distinction between bytes and runes.
