Web Analytics

Loops & Range

Beginner ~35 min read

Loops allow you to execute code repeatedly. Go has only one looping constructโ€”the for loopโ€”but it's incredibly versatile. In this lesson, you'll learn all the ways to use for and the powerful range keyword for iteration.

The For Loop

Go has only one loop keyword: for. It can be used in several ways:

Output
Click Run to execute your code
For Loop Components:
for init; condition; post {
    // loop body
}
  • init: Executed before the first iteration (optional)
  • condition: Evaluated before each iteration (optional)
  • post: Executed at the end of each iteration (optional)

Classic For Loop

// Traditional C-style for loop
for i := 0; i < 5; i++ {
    fmt.Println(i)
}

// Count down
for i := 10; i > 0; i-- {
    fmt.Println(i)
}

// Step by 2
for i := 0; i < 10; i += 2 {
    fmt.Println(i)  // 0, 2, 4, 6, 8
}
Pro Tip: The loop variable (e.g., i) is scoped to the loop. It's not accessible outside the loop body.

While-Style Loops

Go doesn't have a while keyword, but you can use for as a while loop:

Output
Click Run to execute your code

Infinite Loops

Omit all components to create an infinite loop:

// Infinite loop
for {
    fmt.Println("This runs forever!")
    // Use break to exit
    if someCondition {
        break
    }
}

// Common pattern: server loops
for {
    conn, err := listener.Accept()
    if err != nil {
        break
    }
    go handleConnection(conn)
}

The Range Keyword

The range keyword iterates over elements in various data structures:

Output
Click Run to execute your code

Range Over Different Types

Type Syntax Returns
Slice/Array for i, v := range slice index, value
String for i, r := range str index, rune
Map for k, v := range map key, value
Channel for v := range ch value

Range Over Maps

Output
Click Run to execute your code
Important: When ranging over a map, the iteration order is random! Don't rely on any specific order.

Ignoring Values with Blank Identifier

// Only need the index
for i := range numbers {
    fmt.Println("Index:", i)
}

// Only need the value
for _, value := range numbers {
    fmt.Println("Value:", value)
}

// Only need keys from map
for key := range myMap {
    fmt.Println("Key:", key)
}

Break and Continue

Control loop execution with break and continue:

Break - Exit the Loop

// Find first even number
for i := 1; i <= 10; i++ {
    if i%2 == 0 {
        fmt.Println("First even:", i)
        break  // Exit the loop
    }
}

// Search in slice
for _, name := range names {
    if name == "Alice" {
        fmt.Println("Found Alice!")
        break
    }
}

Continue - Skip to Next Iteration

// Print only odd numbers
for i := 1; i <= 10; i++ {
    if i%2 == 0 {
        continue  // Skip even numbers
    }
    fmt.Println(i)
}

// Skip empty strings
for _, str := range strings {
    if str == "" {
        continue
    }
    fmt.Println(str)
}

Labeled Breaks

Break out of nested loops using labels:

outer:
for i := 0; i < 3; i++ {
    for j := 0; j < 3; j++ {
        if i*j > 2 {
            break outer  // Breaks out of both loops
        }
        fmt.Printf("i=%d, j=%d\n", i, j)
    }
}

Common Loop Patterns

1. Counting

// Count from 1 to 10
for i := 1; i <= 10; i++ {
    fmt.Println(i)
}

// Count down
for i := 10; i >= 1; i-- {
    fmt.Println(i)
}

2. Sum/Accumulation

numbers := []int{1, 2, 3, 4, 5}
sum := 0

for _, num := range numbers {
    sum += num
}
fmt.Println("Sum:", sum)  // 15

3. Filtering

numbers := []int{1, 2, 3, 4, 5, 6}
var evens []int

for _, num := range numbers {
    if num%2 == 0 {
        evens = append(evens, num)
    }
}
fmt.Println(evens)  // [2, 4, 6]

4. Finding

names := []string{"Alice", "Bob", "Charlie"}
found := false

for _, name := range names {
    if name == "Bob" {
        found = true
        break
    }
}
fmt.Println("Found Bob:", found)

Common Mistakes

1. Modifying slice while iterating

// โŒ Dangerous - can cause issues
for i, v := range slice {
    slice = append(slice, v*2)  // Modifying while iterating!
}

// โœ… Correct - iterate over a copy or use index-based loop
original := make([]int, len(slice))
copy(original, slice)
for _, v := range original {
    slice = append(slice, v*2)
}

2. Range variable reuse

// โŒ Wrong - all pointers point to same variable
var ptrs []*int
for _, v := range []int{1, 2, 3} {
    ptrs = append(ptrs, &v)  // All point to same v!
}

// โœ… Correct - create new variable
var ptrs []*int
for _, v := range []int{1, 2, 3} {
    v := v  // Create new variable
    ptrs = append(ptrs, &v)
}

3. Infinite loop without break

// โŒ Wrong - runs forever
for {
    fmt.Println("Forever!")
    // No break condition!
}

// โœ… Correct - have an exit condition
count := 0
for {
    fmt.Println("Iteration:", count)
    count++
    if count >= 5 {
        break
    }
}

Exercise: FizzBuzz

Task: Implement the classic FizzBuzz problem.

Requirements:

  • Loop from 1 to 30
  • For multiples of 3, print "Fizz"
  • For multiples of 5, print "Buzz"
  • For multiples of both 3 and 5, print "FizzBuzz"
  • Otherwise, print the number
Show Solution
package main

import "fmt"

func main() {
    for i := 1; i <= 30; i++ {
        // Check for both 3 and 5 first
        if i%3 == 0 && i%5 == 0 {
            fmt.Println("FizzBuzz")
        } else if i%3 == 0 {
            fmt.Println("Fizz")
        } else if i%5 == 0 {
            fmt.Println("Buzz")
        } else {
            fmt.Println(i)
        }
    }
    
    // Alternative solution using string building
    fmt.Println("\n--- Alternative ---")
    for i := 1; i <= 30; i++ {
        output := ""
        if i%3 == 0 {
            output += "Fizz"
        }
        if i%5 == 0 {
            output += "Buzz"
        }
        if output == "" {
            fmt.Println(i)
        } else {
            fmt.Println(output)
        }
    }
}

Summary

  • for is the only loop in Go, but it's very versatile
  • Classic for loop: for init; condition; post
  • While-style loop: for condition
  • Infinite loop: for {}
  • range iterates over slices, arrays, strings, maps, and channels
  • range on slice/array returns index and value
  • range on map returns key and value (random order)
  • break exits the loop, continue skips to next iteration
  • Labeled breaks exit nested loops

What's Next?

Congratulations on completing the Control Flow module! You can now make decisions and repeat code. Next, you'll learn about Functions & Returns, where you'll discover how to organize code into reusable blocks and work with multiple return values.