Go for Loop

Ma Mahalakshmi V Updated 04 Nov 2026
4 min read

Go for Loop

Go has exactly one looping keyword: for. Rather than providing separate while, do-while, and for constructs like many other languages, Go's single for statement is flexible enough to express all of them — traditional counting loops, condition-only loops, and infinite loops.

Each time the loop body runs is called an iteration.

Basic Syntax

for initialization; condition; post {
    // code executed in each iteration
}

The three components:

  • Initialization — runs once, before the loop starts (typically declares a counter variable).
  • Condition — checked before every iteration; the loop continues while it's true and stops the moment it's false.
  • Post statement — runs after every iteration (typically increments or updates the counter).

All three components are optional, but the loop must still be logically controlled somehow, or it runs forever.

Example: Printing Numbers

package main

import "fmt"

func main() {
    for i := 1; i <= 5; i++ {
        fmt.Println("Count:", i)
    }
}

Expected output:

Count: 1
Count: 2
Count: 3
Count: 4
Count: 5

Example: Custom Step Size

package main

import "fmt"

func main() {
    for i := 0; i <= 50; i += 5 {
        fmt.Println(i)
    }
}

This increments by 5 each iteration instead of 1.

Other Forms of for

Because all three components are optional, Go's single for keyword covers cases other languages split into separate constructs.

A "while" loop — condition only:

count := 0
for count < 5 {
    fmt.Println(count)
    count++
}

An infinite loop — no components at all, exited with break:

for {
    // runs forever until a break statement is reached
}

This form is common for servers and long-running processes that loop until an external signal tells them to stop.

Using continue

continue skips the rest of the current iteration and jumps straight to the next one, re-checking the condition.

package main

import "fmt"

func main() {
    for i := 1; i <= 6; i++ {
        if i == 4 {
            continue
        }
        fmt.Println(i)
    }
}

Expected output:

1
2
3
5
6

Notice 4 is skipped, but the loop still continues through 5 and 6 — continue does not stop the loop, only the current pass through it.

Using break

break exits the loop immediately, regardless of the loop's condition.

package main

import "fmt"

func main() {
    for i := 1; i <= 6; i++ {
        if i == 4 {
            break
        }
        fmt.Println(i)
    }
}

Expected output:

1
2
3

Once i reaches 4, the loop stops entirely — 5 and 6 are never reached.

Nested Loops

A loop can contain another loop. The inner loop runs to completion for every single iteration of the outer loop.

package main

import "fmt"

func main() {
    colors := []string{"Red", "Blue"}
    items := []string{"Pen", "Book", "Bag"}

    for i := 0; i < len(colors); i++ {
        for j := 0; j < len(items); j++ {
            fmt.Println(colors[i], items[j])
        }
    }
}

Note: break and continue inside a nested loop only affect the innermost loop by default. To break out of an outer loop from inside a nested one, label the outer loop and reference that label:

outer:
for i := 0; i < len(colors); i++ {
    for j := 0; j < len(items); j++ {
        if colors[i] == "Blue" {
            break outer // exits both loops immediately
        }
        fmt.Println(colors[i], items[j])
    }
}

The range Keyword

range simplifies iterating over arrays, slices, strings, and maps, automatically producing an index (or key) and a value on each pass.

for index, value := range collection {
    // code
}

Example: Iterating with range

package main

import "fmt"

func main() {
    languages := []string{"Go", "Python", "Java"}

    for index, value := range languages {
        fmt.Printf("Index: %d, Value: %s\n", index, value)
    }
}

Expected output:

Index: 0, Value: Go
Index: 1, Value: Python
Index: 2, Value: Java

Ignoring the Index or the Value

Use the blank identifier _ to discard whichever part you don't need — Go requires every declared variable to be used, so _ is the idiomatic way to signal "I'm intentionally ignoring this."

Ignore the index:

for _, value := range languages {
    fmt.Println(value)
}

Ignore the value:

for index := range languages {
    fmt.Println(index)
}

range is covered again in the Arrays, Slices, and Maps lessons, since each of those data structures has its own small variations on how range behaves — for example, ranging over a map yields keys and values but in no guaranteed order, while ranging over a string yields byte positions and Unicode code points rather than plain indices.

Common Mistakes

  • Forgetting the post statement (i++) and accidentally writing an infinite loop.
  • Modifying the loop variable inside the body in a way that unintentionally changes how many times the loop runs — this works, but is easy to get wrong and usually a sign the logic should be restructured.
  • Trying to use break/continue to affect an outer loop without a label, and being surprised when only the inner loop is affected.

0 Comments

Reviewed before they appear

No comments yet.

Go
Ask about this post
AI Ask about this post

Ask questions about Go for Loop and get answers drawn from it.

Signed-in readers only.