Loops and Iteration
Overview
Go has only one looping construct: the for loop. This single keyword handles all looping patterns.
The Basic for Loop
for i := 0; i < 10; i++ {
fmt.Println(i)
}The while Loop (Condition Only)
n := 1
for n < 100 {
n *= 2
}The Infinite Loop
for {
if done {
break
}
}The range Loop
Slices and Arrays
nums := []int{10, 20, 30}
for i, v := range nums {
fmt.Printf("%d: %d\n", i, v)
}
for _, v := range nums { // Value only
fmt.Println(v)
}Maps
ages := map[string]int{"Alice": 30, "Bob": 25}
for key, value := range ages {
fmt.Printf("%s: %d\n", key, value)
}Strings
for i, r := range "Hello" {
fmt.Printf("%d: %c\n", i, r)
}Channels
for v := range ch { // Exits when channel closes
fmt.Println(v)
}Iterators (Go 1.23+)
Go 1.23 introduced “range-over-func,” allowing you to use range with custom iterator functions.
Sequence Iterators
A sequence iterator is a function that takes a yield function: func(yield func(V) bool) (single value) or func(yield func(K, V) bool) (key-value).
func All[T any](s []T) iter.Seq[T] {
return func(yield func(T) bool) {
for _, v := range s {
if !yield(v) {
return
}
}
}
}
// Usage
for v := range All(nums) {
fmt.Println(v)
}Pull Iterators
For more control, you can use pull iterators:
next, stop := iter.Pull(All(nums))
defer stop()
for {
v, ok := next()
if !ok {
break
}
fmt.Println(v)
}Loop Control
break and continue
for i := 0; i < 10; i++ {
if i == 5 {
break // Exit loop
}
if i%2 == 0 {
continue // Skip to next iteration
}
fmt.Println(i)
}Labels for Nested Loops
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i == 1 && j == 1 {
break outer // Break both loops
}
}
}Common Patterns
// Reverse iteration
for i := len(items) - 1; i >= 0; i-- {
process(items[i])
}
// Step by N
for i := 0; i < 100; i += 10 {
fmt.Println(i)
}Summary
| Pattern | Syntax |
|---|---|
| Classic for | for i := 0; i < n; i++ {} |
| While loop | for condition {} |
| Infinite loop | for {} |
| Range | for i, v := range slice {} |
| Iterators | for v := range myIter() {} |