Learn Go← Dashboard

if/else, switch, the lone for loop, break, continue.

The for Loop (Go has only one)

Go has exactly one loop keyword: for. There is no while, no do, no foreach. But for has four forms.

1. C-style for

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

2. While form (just the condition)

n := 10
for n > 0 {
    n--
}

3. Infinite loop

for {
    if done() {
        break
    }
}

Use break to exit and continue to skip to the next iteration.

4. Range over an integer (Go 1.22+)

Since Go 1.22 you can range over an int to loop that many times — no counter variable needed:

for i := range 5 {
    fmt.Println(i) // 0, 1, 2, 3, 4
}

Equivalent to the C-style form but tidier when you don't have a collection.

5. for ... range — iterate over a collection

This is the workhorse. It works for arrays, slices, maps, strings, and channels.

go playground
Loading...

| Collection | Range yields | | ---------- | ----------------------------- | | Array / slice | index, value | | Map | key, value (random order!) | | String | byte-index, rune | | Channel | one value at a time |

Loop variables in closures (the famous gotcha)

Before Go 1.22, the loop variable was shared across iterations. Every closure captured the same i and saw the final value:

// Before Go 1.22: prints "3 3 3"
for i := 0; i < 3; i++ {
    go func() { fmt.Println(i) }()
}

Since Go 1.22, each iteration gets its own fresh copy, so the above prints 0 1 2 in some order. If you're on older Go, work around it by shadowing:

for i := 0; i < 3; i++ {
    i := i               // shadow with a per-iteration copy
    go func() { fmt.Println(i) }()
}

Labels with break and continue

For nested loops you can label them and break out of an outer one:

go playground
Loading...
`for k, v := range m { … }` where `m` is a map. What can you assume about iteration order?