Control Flow

Master if/else, for loops, switch, and range — Go's clean approach to program flow.

Beginner 30 min read 🐹 Go

if / else

Go's if statement doesn't need parentheses around the condition, but the braces are mandatory. A unique Go feature: you can include a short statement before the condition, commonly used for error checking.

package main

import "fmt"

func main() {
    age := 20

    // Basic if/else
    if age >= 18 {
        fmt.Println("Adult")
    } else if age >= 13 {
        fmt.Println("Teenager")
    } else {
        fmt.Println("Child")
    }

    // if with short statement (very common in Go)
    if num := 42; num%2 == 0 {
        fmt.Println(num, "is even")
    } // num is NOT accessible here - scoped to if block
}
Output
Adult
42 is even
Key Takeaway: The if val := expr; condition pattern is idiomatic Go. You'll see it everywhere, especially with error handling: if err := doSomething(); err != nil { ... }

for — The Only Loop

Go has only one looping construct: for. But it covers all cases — traditional C-style, while-like, and infinite loops. No while or do-while keywords exist.

// C-style for loop
for i := 0; i < 5; i++ {
    fmt.Print(i, " ")
}
fmt.Println() // 0 1 2 3 4

// While-style (condition only)
n := 1
for n < 100 {
    n *= 2
}
fmt.Println(n) // 128

// Infinite loop (break to exit)
count := 0
for {
    count++
    if count > 3 {
        break
    }
}
fmt.Println("Count:", count) // 4
Output
0 1 2 3 4
128
Count: 4

range — Iterating Over Collections

range iterates over slices, maps, strings, and channels. It returns both the index/key and value:

// Range over slice
fruits := []string{"apple", "banana", "cherry"}
for i, fruit := range fruits {
    fmt.Printf("%d: %s\n", i, fruit)
}

// Ignore index with _
for _, fruit := range fruits {
    fmt.Println(fruit)
}

// Range over map
scores := map[string]int{"Alice": 95, "Bob": 87}
for name, score := range scores {
    fmt.Printf("%s: %d\n", name, score)
}

// Range over string (iterates runes, not bytes)
for i, ch := range "Go!" {
    fmt.Printf("%d: %c\n", i, ch)
}

switch

Go's switch is cleaner than C/Java: no break needed — cases don't fall through by default. Use fallthrough explicitly if you want it (rare).

day := "Tuesday"
switch day {
case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday":
    fmt.Println("Weekday")
case "Saturday", "Sunday":
    fmt.Println("Weekend")
default:
    fmt.Println("Unknown")
}

// Switch without a condition (clean if/else chain)
hour := 14
switch {
case hour < 12:
    fmt.Println("Morning")
case hour < 17:
    fmt.Println("Afternoon")
default:
    fmt.Println("Evening")
}
Output
Weekday
Afternoon

⚠️ Common Mistake: Expecting fall-through

Coming from C/Java, you might expect cases to fall through. In Go, they don't. Each case breaks automatically. If you need fall-through (rare), add the fallthrough keyword explicitly.

Practice Exercises

Easy Hello World Variant

Modify the example to accept user input and print a personalized greeting.

Easy Code Reading

Read through the code examples above and predict the output before running them.

Medium Extend the Example

Take one code example and add error handling, input validation, or a new feature.