Skip to content

Go Loops: For, While, and Control Flow

Overview

This guide will try to cover the for loop, while loops(style), and essential control statements like break and continue, building upon our foundation of data types and variables.

Key Points

  • Go has only one loop construct: the for loop
  • Multiple patterns: classic, while-style, infinite, and range loops
  • Powerful control flow with break and continue
  • Clean and readable iteration patterns
  • Efficient performance with proper loop design

Go's Loop

Go simplifies loop constructs by providing a single, versatile for loop that can handle all iteration needs. This design promotes consistency and reduces complexity.

Loop Patterns in Go

graph TD
    A[Go For Loop] --> B[Classic For]
    A --> C[While-Style]
    A --> D[Infinite Loop]
    A --> E[Range Loop]
    B --> B1[Init; Condition; Post]
    C --> C1[Condition Only]
    D --> D1[No Conditions]
    E --> E1[Iterate Collections]
    style A fill:#000,stroke:#000,stroke-width:2px,color:#555

Classic For Loop

The classic for loop provides precise control over initialization, condition checking, and post-iteration operations.

Basic Structure

Classic For Loop Syntax

classic_for.go
package main

import "fmt"

func main() {
    for i := 0; i < 5; i++ {
        fmt.Printf("Iteration %d\n", i)
    }

    // Output:
    // Iteration 0
    // Iteration 1
    // Iteration 2
    // Iteration 3
    // Iteration 4
}

Three Components

  1. Init: i := 0 - executed once before the loop
  2. Condition: i < 5 - checked before each iteration
  3. Post: i++ - executed after each iteration
flexible_init.go
package main

import "fmt"

func main() {
    // Multiple variables in init
    for i, j := 0, 10; i < j; i, j = i+1, j-1 {
        fmt.Printf("i=%d, j=%d\n", i, j)
    }

    // Output:
    // i=0, j=10
    // i=1, j=9
    // i=2, j=8
    // i=3, j=7
    // i=4, j=6
}
step_sizes.go
package main

import "fmt"

func main() {
    // Increment by 2
    fmt.Println("Even numbers:")
    for i := 0; i <= 10; i += 2 {
        fmt.Printf("%d ", i)
    }
    fmt.Println()

    // Decrement
    fmt.Println("Countdown:")
    for i := 5; i >= 0; i-- {
        fmt.Printf("%d ", i)
    }
    fmt.Println()

    // Output:
    // Even numbers: 0 2 4 6 8 10
    // Countdown: 5 4 3 2 1 0
}

While-Style Loops

Go's for loop can mimic traditional while loops by omitting the init and post statements.

While Loop Pattern

While-Style Loops

while_basic.go
package main

import "fmt"

func main() {
    i := 0
    for i < 5 {
        fmt.Printf("Count: %d\n", i)
        i++
    }

    // Output:
    // Count: 0
    // Count: 1
    // Count: 2
    // Count: 3
    // Count: 4
}
input_processing.go
package main

import "fmt"

func main() {
    var input string

    for input != "quit" {
        fmt.Print("Enter command (or 'quit' to exit): ")
        fmt.Scanln(&input)

        if input != "quit" {
            fmt.Printf("You entered: %s\n", input)
        }
    }

    fmt.Println("Goodbye!")
}
condition_based.go
package main

import (
    "fmt"
    "math/rand"
)

func main() {
    target := 7
    attempts := 0

    for {
        guess := rand.Intn(10) + 1
        attempts++
        fmt.Printf("Attempt %d: Guessed %d\n", attempts, guess)

        if guess == target {
            fmt.Printf("Found target %d in %d attempts!\n", target, attempts)
            break
        }
    }
}

Infinite Loops

Infinite loops are useful for servers, event handlers, and continuous processing scenarios.

Infinite Loop Patterns

infinite_basic.go
package main

import "fmt"

func main() {
    counter := 0
    for {
        fmt.Printf("Running... %d\n", counter)
        counter++

        if counter >= 3 {
            fmt.Println("Breaking out of infinite loop")
            break
        }
    }
}
server_loop.go
package main

import (
    "fmt"
    "time"
)

func main() {
    fmt.Println("Server starting...")

    for {
        // Simulate processing
        fmt.Println("Processing request...")
        time.Sleep(1 * time.Second)

        // In a real server, you'd handle actual requests here
        // {condition}

        // This example will run forever (Ctrl+C to stop)
        break // Remove this to see infinite behavior
    }
}

Break and Continue

Control flow statements provide fine-grained control over loop execution.

Break Statement

The break statement immediately exits the loop.

Break Statement Usage

break_simple.go
package main

import "fmt"

func main() {
    for i := 0; i < 10; i++ {
        fmt.Printf("i = %d\n", i)

        if i == 5 {
            fmt.Println("Breaking at 5")
            break
        }
    }
    fmt.Println("Loop ended")

    // Output:
    // i = 0
    // i = 1
    // i = 2
    // i = 3
    // i = 4
    // i = 5
    // Breaking at 5
    // Loop ended
}
search_break.go
package main

import "fmt"

func main() {
    numbers := []int{1, 3, 7, 9, 12, 15, 18}
    target := 12

    for i, num := range numbers {
        if num == target {
            fmt.Printf("Found %d at index %d\n", target, i)
            break
        }
        fmt.Printf("Checking %d at index %d\n", num, i)
    }
}

Range Syntax

The syntax range numbers iterate through the numbers array one by one. Like a map function in Javascript.

nested_break.go
package main

import "fmt"

func main() {
    found := false

    for i := 0; i < 3 && !found; i++ {
        for j := 0; j < 3; j++ {
            fmt.Printf("i=%d, j=%d\n", i, j)

            if i == 1 && j == 1 {
                fmt.Println("Found target position!")
                found = true
                break // Only breaks inner loop
            }
        }
    }
}

Continue Statement

The continue statement skips the rest of the current iteration and moves to the next one.

Continue Statement Usage

continue_skip.go
package main

import "fmt"

func main() {
    fmt.Println("Odd numbers from 1 to 10:")
    for i := 1; i <= 10; i++ {
        if i%2 == 0 {
            continue // Skip even numbers
        }
        fmt.Printf("%d ", i)
    }
    fmt.Println()

    // Output: 1 3 5 7 9
}
data_validation.go
package main

import "fmt"

func main() {
    data := []int{1, -2, 3, 0, 5, -7, 8}

    fmt.Println("Processing positive numbers:")
    for i, value := range data {
        if value <= 0 {
            fmt.Printf("Skipping invalid value %d at index %d\n", value, i)
            continue
        }

        // Process valid data
        result := value * 2
        fmt.Printf("Processed %d -> %d\n", value, result)
    }
}
error_handling.go
package main

import (
    "fmt"
    "strconv"
)

func main() {
    inputs := []string{"1", "abc", "3", "def", "5"}

    for i, input := range inputs {
        num, err := strconv.Atoi(input)
        if err != nil {
            fmt.Printf("Error converting '%s' at index %d: %v\n", input, i, err)
            continue
        }

        fmt.Printf("Successfully converted '%s' to %d\n", input, num)
    }
}

Advanced Loop Patterns

Labeled Breaks and Continues

For complex nested loops, Go provides labeled breaks and continues.

Labeled Control Flow

labeled_break.go
package main

import "fmt"

func main() {
    fmt.Println("Searching in 2D array:")

    outer:
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            fmt.Printf("Checking position [%d][%d]\n", i, j)

            if i == 1 && j == 1 {
                fmt.Println("Found target! Breaking out of both loops")
                break outer
            }
        }
    }

    fmt.Println("Search completed")
}
labeled_continue.go
package main

import "fmt"

func main() {
    fmt.Println("Processing matrix rows:")

    rowLoop:
    for i := 0; i < 3; i++ {
        fmt.Printf("Processing row %d:\n", i)

        for j := 0; j < 3; j++ {
            if j == 1 && i%2 == 0 {
                fmt.Printf("  Skipping rest of row %d\n", i)
                continue rowLoop
            }
            fmt.Printf("  Processing element [%d][%d]\n", i, j)
        }
    }
}

Loop Performance Optimization

Performance Considerations

performance_bounds.go
package main

import "fmt"

func main() {
    data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

    // Good: Calculate length once
    length := len(data)
    for i := 0; i < length; i++ {
        fmt.Printf("Processing %d\n", data[i])
    }

    // Even better: Use range for slices
    for i, value := range data {
        fmt.Printf("Index %d: %d\n", i, value)
    }
}
minimize_work.go
package main

import "fmt"

func main() {
    numbers := []int{1, 2, 3, 4, 5}

    // Pre-calculate expensive operations
    multiplier := 2
    prefix := "Number: "

    for _, num := range numbers {
        result := num * multiplier
        fmt.Printf("%s%d\n", prefix, result)
    }
}

Best Practices

Loop Best Practices

  1. Choose the Right Pattern

    • Use classic for when you need precise control
    • Use while-style for condition-based loops
    • Use range for collections (covered in Range documentation)
  2. Control Flow Guidelines

    • Use break to exit loops early
    • Use continue to skip iterations
    • Use labeled breaks/continues for nested loops
  3. Performance Tips

    • Pre-calculate loop bounds when possible
    • Minimize work inside loop bodies
    • Consider loop unrolling for critical paths
  4. Readability

    • Use descriptive variable names
    • Keep loop bodies concise
    • Comment complex loop logic

Common Pitfalls

  • Infinite Loops: Always ensure loop conditions can become false
  • Off-by-One Errors: Be careful with < vs <= conditions
  • Modifying Loop Variables: Avoid changing loop counters inside the loop body
  • Nested Loop Complexity: Consider extracting inner loops into functions

Quick Reference

Key Takeaways

  1. Single Loop Construct: Go uses only for loops for all iteration needs
  2. Multiple Patterns: Classic, while-style, infinite, and range loops
  3. Control Flow: break and continue provide fine-grained control
  4. Labels: Use labeled breaks/continues for complex nested scenarios
  5. Performance: Choose appropriate patterns and optimize loop bodies

Remember

"Go's unified loop approach promotes consistency and simplicity. Master the for loop patterns and you'll handle any iteration scenario efficiently."