Control Flow in Go: Your Traffic Controller 🚦
Imagine you’re a traffic controller at a busy intersection. Your job is to decide which cars go where based on different conditions. That’s exactly what control flow does in Go—it decides which code runs and when!
The Big Picture
graph TD A[Start Program] --> B{Make a Decision?} B -->|Yes| C[If/Switch] B -->|Repeat?| D[For Loop] C --> E[Execute Code] D --> E E --> F[Continue or Stop]
Think of your Go program as a road trip. Control flow is your GPS telling you:
- If statements = “Turn left IF the road is clear”
- Switch statements = “Choose exit 1, 2, or 3 based on your destination”
- For loops = “Keep driving UNTIL you reach home”
1. If Statements: The Simple Gate
An if statement is like a gate that only opens when the password is correct.
How It Works
age := 10
if age >= 18 {
fmt.Println("You can vote!")
} else {
fmt.Println("Wait a few years!")
}
What happens:
- Go checks: “Is age 18 or more?”
- If YES → prints “You can vote!”
- If NO → prints “Wait a few years!”
The Three Flavors
| Type | When to Use | Example |
|---|---|---|
if only |
One condition | if sunny { play() } |
if-else |
Two choices | if sunny { play() } else { read() } |
if-else if-else |
Many choices | See below |
score := 85
if score >= 90 {
fmt.Println("A Grade!")
} else if score >= 80 {
fmt.Println("B Grade!")
} else if score >= 70 {
fmt.Println("C Grade!")
} else {
fmt.Println("Keep trying!")
}
// Output: B Grade!
2. If with Initialization: The Secret Shortcut 🔑
Go has a superpower that other languages don’t: you can create a variable AND check it in one line!
Without Initialization (The Long Way)
err := doSomething()
if err != nil {
fmt.Println("Oops!")
}
// err still exists here... taking up space!
With Initialization (The Go Way)
if err := doSomething(); err != nil {
fmt.Println("Oops!")
}
// err disappears here! Clean and tidy!
The magic: The variable err only lives inside the if block. Once the block ends, it vanishes like magic!
Real Example
if length := len("Hello"); length > 3 {
fmt.Println("Long word!", length)
}
// length doesn't exist here anymore
đź’ˇ Pro Tip: Use this pattern when you only need the variable for the check. It keeps your code clean!
3. Switch Statement: The Menu Selector 🍽️
Imagine a restaurant menu. Instead of asking “Is it pizza? No? Is it burger? No? Is it salad?” you just say “I want item #2!” That’s a switch!
Basic Switch
day := "Monday"
switch day {
case "Monday":
fmt.Println("Start of week!")
case "Friday":
fmt.Println("Almost weekend!")
case "Saturday", "Sunday":
fmt.Println("Weekend!")
default:
fmt.Println("Regular day")
}
Key Points:
- Go automatically breaks after each case (no need to write
break!) defaultcatches everything else (like “else”)- You can group multiple values:
"Saturday", "Sunday"
Switch vs Multiple If
graph LR A[Multiple Values?] -->|Yes| B[Use Switch] A -->|No| C[Use If] B --> D[Cleaner Code] C --> E[Simple Checks]
4. Switch Without Expression: The Smart Detective 🔍
This is like a detective asking different questions until one is true!
score := 85
switch {
case score >= 90:
fmt.Println("Excellent!")
case score >= 80:
fmt.Println("Great job!")
case score >= 70:
fmt.Println("Good work!")
default:
fmt.Println("Keep practicing!")
}
Notice: No value after switch! Each case is a separate condition.
When to Use
| Regular Switch | Switch Without Expression |
|---|---|
| Comparing ONE value | Different conditions |
switch color { |
switch { |
case "red": |
case age > 18: |
5. Type Switch: The Shape Shifter đźŽ
Sometimes you don’t know what type of data you have. Type switch helps you figure it out!
func checkType(x interface{}) {
switch v := x.(type) {
case int:
fmt.Println("It's a number:", v)
case string:
fmt.Println("It's text:", v)
case bool:
fmt.Println("It's true/false:", v)
default:
fmt.Println("Unknown type!")
}
}
checkType(42) // It's a number: 42
checkType("hello") // It's text: hello
checkType(true) // It's true/false: true
The Secret Sauce: x.(type) reveals what type x really is!
6. For Loop Variants: The Repeat Button 🔄
Go only has ONE loop keyword: for. But it can do EVERYTHING!
The Classic For Loop
Like counting from 1 to 10:
for i := 1; i <= 5; i++ {
fmt.Println(i)
}
// Output: 1, 2, 3, 4, 5
Three parts:
i := 1→ Start at 1i <= 5→ Keep going while i is 5 or lessi++→ Add 1 after each round
The While-Style Loop
Go doesn’t have while, but for can act like one:
count := 0
for count < 3 {
fmt.Println("Count:", count)
count++
}
// Output: Count: 0, Count: 1, Count: 2
The Infinite Loop
Runs forever (until you stop it):
for {
fmt.Println("Forever!")
break // Without this, it never stops!
}
Quick Reference
| Style | Code | Use Case |
|---|---|---|
| Classic | for i := 0; i < 10; i++ |
Count from A to B |
| While-style | for condition |
Unknown iterations |
| Infinite | for { } |
Servers, games |
7. For Range Loop: The Collection Explorer 🗺️
When you have a collection (list, map, string), range helps you visit each item!
Looping Through a Slice (List)
fruits := []string{"apple", "banana", "cherry"}
for index, fruit := range fruits {
fmt.Println(index, fruit)
}
// Output:
// 0 apple
// 1 banana
// 2 cherry
Just the Values (Skip Index)
for _, fruit := range fruits {
fmt.Println(fruit)
}
// Output: apple, banana, cherry
The _ means “I don’t need this!”
Looping Through a Map
ages := map[string]int{
"Alice": 25,
"Bob": 30,
}
for name, age := range ages {
fmt.Println(name, "is", age)
}
Looping Through a String
for i, char := range "Go!" {
fmt.Printf("%d: %c\n", i, char)
}
// 0: G
// 1: o
// 2: !
8. Break and Continue: The Emergency Buttons 🛑
Break: The Exit Door
break says “STOP! I’m done with this loop!”
for i := 1; i <= 10; i++ {
if i == 5 {
break // Exit at 5
}
fmt.Println(i)
}
// Output: 1, 2, 3, 4
Continue: The Skip Button
continue says “Skip this round, go to the next!”
for i := 1; i <= 5; i++ {
if i == 3 {
continue // Skip 3
}
fmt.Println(i)
}
// Output: 1, 2, 4, 5
Visual Guide
graph TD A[Start Loop] --> B{Check Condition} B -->|Continue| C[Skip to Next] B -->|Break| D[Exit Loop] B -->|Normal| E[Run Code] E --> A C --> A
Real-World Example
Finding the first even number:
numbers := []int{1, 3, 5, 4, 7, 8}
for _, n := range numbers {
if n%2 != 0 {
continue // Skip odd numbers
}
fmt.Println("Found even:", n)
break // Stop after finding first
}
// Output: Found even: 4
Putting It All Together 🎯
Here’s a mini-game that uses EVERYTHING we learned:
package main
import "fmt"
func main() {
scores := []int{85, 92, 78, 95, 60}
for i, score := range scores {
// Skip low scores
if score < 70 {
continue
}
// Grade using switch
switch {
case score >= 90:
fmt.Printf("Student %d: A\n", i+1)
case score >= 80:
fmt.Printf("Student %d: B\n", i+1)
default:
fmt.Printf("Student %d: C\n", i+1)
}
}
}
Output:
Student 1: B
Student 2: A
Student 3: C
Student 4: A
Your Control Flow Toolbox đź§°
| Tool | Purpose | Example |
|---|---|---|
if |
Single decision | if x > 0 |
if-else |
Two paths | if x > 0 {} else {} |
if + init |
Clean scope | if err := f(); err != nil |
switch |
Multiple values | switch day { case "Mon": |
switch {} |
Multiple conditions | switch { case x > 10: |
| Type switch | Check types | switch v := x.(type) |
for classic |
Counting | for i := 0; i < 10; i++ |
for while |
Conditional | for condition {} |
for range |
Collections | for i, v := range slice |
break |
Exit loop | break |
continue |
Skip iteration | continue |
Remember! đź§
- If statements are like gates—they let code through based on conditions
- If with init keeps variables in scope—clean and tidy!
- Switch is cleaner than many if-else chains
- Switch without expression checks multiple different conditions
- Type switch discovers what type a value really is
- For loops are the only loop in Go—but they can do everything!
- For range visits every item in a collection
- Break exits the loop completely
- Continue skips to the next iteration
You’re now a Control Flow master! 🎉 Time to practice!