Go has exactly one loop keyword: for. There is no while and no do. That one
keyword takes a few shapes, which together cover every kind of repetition you
need.
The three-component for loop
The classic form has an init statement, a condition, and a post statement,
separated by semicolons. The loop runs while the condition is true.
for i := 0; i < 5; i++ {
fmt.Println(i)
}
i is scoped to the loop, so it disappears once the loop ends.
The while-style loop
Drop the init and post statements and you get a condition-only loop — Go’s
equivalent of a while. The semicolons go away too.
n := 1
for n < 100 {
n *= 2
}
The infinite loop
Drop the condition as well and the loop runs forever. You leave it with break
(or return). This form is common for servers and read loops.
for {
line, ok := next()
if !ok {
break
}
process(line)
}
Ranging over slices and maps
for range walks a collection. Over a slice it yields the index and a copy of
each element:
letters := []string{"a", "b", "c"}
for i, letter := range letters {
fmt.Println(i, letter)
}
Over a map it yields the key and the value, in an unspecified order that can change between runs:
stock := map[string]int{"pens": 4, "books": 7}
for name, qty := range stock {
fmt.Printf("%s: %d\n", name, qty)
}
break and continue
break stops the loop immediately; continue skips to the next iteration.
for i := 1; i <= 10; i++ {
if i%2 != 0 {
continue // skip odd numbers
}
if i > 6 {
break // stop once we pass 6
}
fmt.Println(i)
}
Labels for nested loops
A break or continue normally affects the innermost loop. To target an outer
loop, attach a label to it:
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i+j == 3 {
break outer
}
}
}
Use labels sparingly — they are handy for grid searches but easy to overuse.
A complete example
This program iterates a slice of temperatures, computes their average and finds the peak. It compiles and runs as-is.
package main
import "fmt"
func main() {
temperatures := []float64{18.5, 21.0, 19.5, 24.0, 20.0}
var sum float64
max := temperatures[0]
for i, t := range temperatures {
sum += t
if t > max {
max = t
}
fmt.Printf("day %d: %.1f°C\n", i+1, t)
}
average := sum / float64(len(temperatures))
fmt.Printf("average: %.1f°C, peak: %.1f°C\n", average, max)
}
Running it prints:
day 1: 18.5°C
day 2: 21.0°C
day 3: 19.5°C
day 4: 24.0°C
day 5: 20.0°C
average: 20.6°C, peak: 24.0°C
Common mistakes
- Forgetting that the range value is a copy. Assigning to
tinsidefor i, t := range sdoes not change the slice. Write tos[i]instead. - Relying on map order. Ranging a map gives no stable order; sort the keys first if you need determinism.
- Writing an infinite loop with no exit. A
for {}without a reachablebreakorreturnhangs the program.
Practice
Print the multiplication table for 7, from 7 x 1 up to 7 x 10, one line per
row, like 7 x 3 = 21.
Show the solution
package main
import "fmt"
func main() {
const n = 7
for i := 1; i <= 10; i++ {
fmt.Printf("%d x %d = %d\n", n, i, n*i)
}
}A single three-component for loop counts from 1 to 10 and prints one product
per iteration.
Summary
foris Go’s only loop; it covers counted, while-style and infinite forms.for rangeiterates slices (index, value) and maps (key, value, no order).break,continueand labels give you precise control over the flow.
Next, package repeated logic into functions, and learn about the collections you loop over in arrays and slices.