Go by Example

Range over Built-in Types

The range keyword iterates over slices, maps, strings, channels, and integers - each with different iteration semantics worth knowing.

range iterates over built-in collections. Arrays and slices produce index and value, maps produce key and value, strings produce byte offset and rune, and channels produce values until closed. Since Go 1.22, an integer produces values from zero to one less than itself.

The loop variables depend on the ranged value. A string's index is a byte offset, while its value is a decoded rune.

package main
 
import "fmt"
 
func main() {
    for i, v := range []int{4, 7} {
        fmt.Println(i, v)
    }
 
    scores := map[string]int{"Ada": 10, "Lin": 12}
    for name, score := range scores {
        fmt.Println(name, score)
    }
 
    for i, r := range "é!" {
        fmt.Printf("%d %c\n", i, r)
    }
 
    for i := range 3 {
        fmt.Println(i)
    }
 
    ch := make(chan string, 1)
    ch <- "ready"
    close(ch)
    for v := range ch {
        fmt.Println(v)
    }
}

In production

Map iteration order is unspecified, so sort keys when output must be stable. String indexes advance by each rune's byte width, and len(s) counts bytes. Use strings-and-runes for more on Unicode text.

Enjoyed this? Get more software craft delivered to your inbox.