Go (Golang) Tutorial 0/45 lessons ~6 min read Lesson 8

    Loops

    Go has one looping construct: for.

    Course progress0%
    Focus
    10 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    Go has one looping construct: for. It replaces while, do-while, and traditional for loops from other languages. Go 1.22 fixed the loop variable capture bug — each iteration now gets a fresh variable in range loops, eliminating a classic goroutine closure trap.

    Range iterates over slices, arrays, maps, strings, and channels. Understanding when to use index vs value, iterating maps in random order, and break/continue with labeled loops builds the iteration skills needed for data processing pipelines and batch jobs.

    This lesson covers infinite loops, nested loops, and the range-over-int feature added in Go 1.22 for simple counter loops without manual increment boilerplate.

    The story

    A Prometheus exporter scrapes hundreds of pod metrics from a Kubernetes cluster every 15 seconds. A for loop walks the pod list, a range loop iterates label key-value pairs, and break stops early when a critical alert threshold fires — loops are the engine behind every observability pipeline at scale.

    Both C-style for and for range appear in ETL jobs that transform CloudWatch logs into billing reports for AWS customers.

    Understanding the topic

    Key concepts

    • for init; cond; post { } — C-style three-component loop.
    • for cond { } — while-style loop.
    • for { } — infinite loop; break to exit.
    • for i, v := range slice — index and value; i or v can be _ to ignore.
    • Go 1.22: for i := range n iterates 0 to n-1.
    • break and continue support labels: break Outer for nested loops.
    text
    flowchart TD
    Init[Initialize] --> Cond{Condition?}
    Cond -->|true| Body[Loop Body]
    Body --> Update[Increment]
    Update --> Cond
    Cond -->|false| Exit([Exit])

    Step-by-step explanation

    1. Init runs once; condition checked before each iteration; post runs after body.
    2. Range on slice returns index and copy of element (for struct, copy not reference).
    3. Range on map returns key, value in random order — don't depend on order.
    4. Range on channel receives until channel closed.
    5. break exits innermost loop; labeled break exits specified outer loop.
    6. continue skips to next iteration.

    Practical code example

    Processing a batch of transactions with range and labeled break:

    go
    package main
    import "fmt"
    type Transaction struct {
    ID int
    Amount float64
    Valid bool
    }
    func processBatch(txs []Transaction) (processed int, total float64) {
    Outer:
    for i, tx := range txs {
    if !tx.Valid {
    continue
    }
    if tx.Amount < 0 {
    fmt.Printf("invalid amount at index %d, stopping batch\n", i)
    break Outer
    }
    total += tx.Amount
    processed++
    }
    return
    }
    func main() {
    txs := []Transaction{
    {1, 100, true}, {2, 50, true}, {3, -10, true}, {4, 200, true},
    }
    n, sum := processBatch(txs)
    fmt.Printf("processed=%d total=%.2f\n", n, sum)
    for i := range 3 { // Go 1.22+
    fmt.Printf("tick %d\n", i)
    }
    }

    Output

    invalid amount at index 2, stopping batch
    processed=2 total=150.00
    tick 0
    tick 1
    tick 2

    Line-by-line code explanation

    • for i := 0; i < len(pods); i++ is the classic indexed loop when you need position.
    • for _, pod := range pods iterates values while discarding the index with _.
    • for key, val := range pod.Labels walks map entries — order is randomized by design.
    • for { ... } creates an infinite loop — common in servers until break or return.
    • if pod.Status == "Failed" { break } exits the loop early on a critical condition.
    • continue skips to the next iteration when a pod is not ready yet.
    • for i := range 10 (Go 1.22+) loops integers 0 through 9 without manual increment.
    • sum += pod.CPUm accumulates a total inside the loop body.

    Key takeaway: Go 1.22 per-iteration loop vars fix goroutine bugs. Use labeled break sparingly — extract function often clearer.

    Real-world use

    Where you'll use this in production

    • Batch processing records from database query results.
    • Retry loops with exponential backoff in HTTP clients.
    • Worker pools consuming from channels in for-range.
    • Parsing and transforming CSV/JSON array elements.

    Best practices

    • Use for range as default iteration style.
    • Modify slice elements by index: slice[i].Field = val (range value is copy).
    • Extract loop body to function when loop exceeds ~15 lines.
    • Use for i := range n (Go 1.22+) for simple counters.
    • Avoid modifying map while ranging — undefined behavior.
    • Prefer slices over indexed loops when functional style fits.

    Common mistakes

    • Taking address of range variable in goroutine pre-1.22 — fixed but know the history.
    • Modifying map during range — can panic or skip entries.
    • Assuming map iteration order — random by design.
    • Off-by-one with manual for loops when range suffices.
    • Infinite loop without break condition or context cancellation.

    Advanced interview questions

    Q1BeginnerHow many loop types does Go have?
    One — for — used as for, while, and infinite loop with different clause forms.
    Q2Beginnercontinue vs break?
    continue skips to next iteration; break exits the loop entirely.
    Q3IntermediateRange over slice — value or reference?
    Value is copy; modify via index slice[i] for struct fields.
    Q4IntermediateBreak out of nested loops?
    Use label: Outer: for { for { break Outer } } or extract to function with return.
    Q5AdvancedPaginated API fetch until no more pages without loading all.
    for { resp, err := client.Get(url); parse nextToken; if nextToken == "" { break }; url = nextURL } with context timeout.

    Summary

    for is Go's only loop — flexible as for, while, and infinite. range iterates slices, maps, strings, channels; Go 1.22 adds range n. Modify slice elements by index; range value is a copy. Use labeled break/continue or extract functions for nested control. Next lesson: functions, parameters, and variadic args.

    Ready to mark this lesson complete?Track your journey across the entire course.