ZetCode

Golang range keyword

last modified May 1, 2026

The range keyword is one of Go's most versatile tools for iteration. It allows programmers to traverse data structures without manually managing loop counters or boundary conditions.

The range keyword facilitates iteration over arrays, slices, maps, strings, channels, and—as of more recent Go versions—integers and iterator functions.

Basic range over a slice

When used with a slice or array, range returns two values: the current index and a copy of the element at that index.

basic_range.go
package main

import "fmt"

func main() {
    fruits := []string{"apple", "banana", "cherry"}
    
    for index, fruit := range fruits {
        fmt.Printf("Index: %d, Value: %s\n", index, fruit)
    }
}

Important Note: The value returned by range is a copy. If you modify the fruit variable in the example above, the original slice remains unchanged. To modify slice elements, use the index: fruits[index] = "new value".

Range with maps

Iterating over a map returns the key and the value. Because maps are hash tables, Go explicitly randomizes the iteration order to prevent programmers from relying on any specific sequence.

map_range.go
package main

import "fmt"

func main() {
    counts := map[string]int{"A": 10, "B": 20, "C": 30}
    
    for key, val := range counts {
        fmt.Printf("Key: %s, Value: %d\n", key, val)
    }
}

Since the order of iteration over maps is randomized, you may see different outputs each time you run the program. This design choice encourages developers to write code that does not depend on the order of map elements, leading to more robust and predictable programs.

Range with strings

Ranging over a string is unique because it iterates over Runes (Unicode code points) rather than bytes.

string_range.go
package main

import "fmt"

func main() {
    // "世" is a multi-byte character
    text := "Go世"
    
    for pos, char := range text {
        fmt.Printf("Character %c starts at byte position %d\n", char, pos)
    }
}

Notice that the index may skip numbers (e.g., from 0 to 1, then to 4) if a character occupies multiple bytes in UTF-8.

Range over Integers (Go 1.22+)

Introduced in Go 1.22, you can now range over an integer directly. This serves as a cleaner alternative to the traditional for i := 0; i < n; i++ loop.

int_range.go
package main

import "fmt"

func main() {
    // Iterates from 0 to 4
    for i := range 5 {
        fmt.Print(i, " ")
    }
}

This will output: 0 1 2 3 4 . The loop variable i takes on values from 0 up to (but not including) the specified integer.

Range over Channels

When ranging over a channel, the loop continues to receive values until the channel is closed. If the channel is empty but not closed, the loop blocks and waits for the next value.

channel_range.go
package main

import "fmt"

func main() {
    ch := make(chan int, 3)
    ch <- 10
    ch <- 20
    close(ch)
    
    for val := range ch {
        fmt.Println("Received:", val)
    }
}

Range over Iterators (Go 1.23+)

Go 1.23 introduced "iterators" (functions with the signature func(yield func(...) bool)). This allows you to create custom sequences that can be used directly with the range keyword.

iterator_range.go
package main

import (
    "fmt"
    "iter"
)

// Backward returns an iterator that traverses a slice in reverse
func Backward[E any](s []E) iter.Seq2[int, E] {
    return func(yield func(int, E) bool) {
        for i := len(s) - 1; i >= 0; i-- {
            if !yield(i, s[i]) {
                return
            }
        }
    }
}

func main() {
    nums := []int{10, 20, 30}
    for i, n := range Backward(nums) {
        fmt.Printf("Index %d: %d\n", i, n)
    }
}

This example defines a custom iterator that traverses a slice in reverse. The yield function is called for each element, allowing the range loop to iterate over the sequence seamlessly.

Ignoring index or value

If you only need the value, use the blank identifier (_) to discard the index. If you only need the index, you can omit the second variable entirely.

for _, v := range slice { /* use only value */ }
for i := range slice    { /* use only index */ }

Source

Go language specification

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Golang tutorials.