bucle-for-go-unico-loop

For Loop in Go: Iteration Forms and Infinite Loops

  • 4 min

The for loop in Go is the only repetitive structure in the language. With it, we create classic loops, while-style loops, and iterations over collections.

If you come from C, Java, or JavaScript, you’re used to having an arsenal of loops: for, while, do-while, foreach… Sometimes you use one, sometimes another, and sometimes you argue with your team about which is more efficient.

In Go, the designers cut to the chase. Only the for loop exists.

Nothing else is needed. The for loop can behave like traditional loops simply by omitting parts of its syntax.

Equivalents to Other Loops

All the common forms are expressed with for:

Traditional Loop TypeIn Go it’s written…Syntax
for (i=0; i<10; i++)classic forfor i:=0; i<10; i++
while (condition)conditional forfor condition
while (true)infinite forfor
do-whileDoes not existSimulated with an infinite for + if break at the end

The Classic for Loop

This is the form we all know, identical to C or Java, but without parentheses (just like if).

Syntax: for initialization; condition; post { ... }

package main

import "fmt"

func main() {
    // Print from 0 to 4
    for i := 0; i < 5; i++ {
        fmt.Println("Counter:", i)
    }
}
Copied!

Notice that the variable i is declared with := inside the loop itself. This means i only exists inside the loop. If you try to access it outside, you’ll get an error.

The for as while

In other languages, we use while when we don’t know how many iterations we’ll perform, but rather depend on a boolean condition.

In Go, to achieve this, we simply omit the initialization and post parts. We leave only the condition.

func main() {
    counter := 1

    // This is equivalent to: while (counter < 100)
    for counter < 100 {
        counter *= 2
        fmt.Println("The counter is now:", counter)
    }
}
Copied!

There’s no need for a new keyword: if we only write a condition, it behaves like a while.

The Infinite Loop

What if we want a loop that never ends (or until we manually stop it)? This is the typical case of a web server listening for requests or a game in its game loop.

In Go, we omit everything.

func main() {
    for {
        fmt.Println("This never stops!")

        // We'll need a mechanism to exit, or Ctrl+C
    }
}
Copied!

This is the canonical way to do a while(true) in Go.

Loop Control with break and continue

As in other languages, we have two keywords to alter the normal flow inside a loop:

  • break: Breaks the loop immediately and exits it.
  • continue: Skips the current iteration and jumps directly to the next one (executing the “post” step if it’s a classic for).

Example with break

We are looking for a number and want to stop as soon as we find it.

for i := 0; i < 10; i++ {
    if i == 5 {
        fmt.Println("Found 5! We're leaving.")
        break // Exits the for loop immediately
    }
    fmt.Println("Searching...", i)
}
Copied!

Example with continue

We want to print only the odd numbers.

for i := 0; i < 5; i++ {
    if i%2 == 0 {
        continue // It's even, skip this iteration
    }
    fmt.Println("Odd:", i)
}
Copied!

Labels in Nested Loops

This is something you don’t see every day, but it’s very useful when working with complex algorithms. If you have a loop inside another loop and want to do a break that exits both, you can use labels.

func main() {
    // Define a label called "OuterLoop"
OuterLoop:
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            fmt.Println(i, j)
            if i == 1 && j == 1 {
                fmt.Println("Breaking everything!")
                break OuterLoop // Breaks the labeled outer loop
            }
        }
    }
    fmt.Println("End of program")
}
Copied!

Without the label, the break would only exit the inner loop (j), and the outer loop (i) would continue executing.

Iteration over Collections

Although we will dedicate a full article to collections, it’s impossible to talk about for without briefly mentioning the range clause. It’s the equivalent of the foreach in C# or for..of in JS.

names := []string{"Luis", "Juan", "Ana"}

for index, value := range names {
    fmt.Printf("Position %d: %s\n", index, value)
}
Copied!