thecodex.expert · The Codex Family of Knowledge
Go

Iterators and range

Go 1.23 added a genuinely new language feature: range can now iterate over a function, letting you define custom, lazy sequences without building a slice first.

Go 1.26 range-over-func, Go 1.23 Last verified:
Canonical Definition

range has always worked over slices, arrays, maps, strings, channels, and (since Go 1.22) integers. Go 1.23 (released August 2024) added range-over-func: a for range loop can iterate over a function matching one of a few specific signatures, letting you define a custom, lazy sequence — skipping items, stopping early, or generating values on demand — without first materializing a slice.

range over integers (Go 1.22)

A smaller but handy addition: since Go 1.22, ranging over a plain integer counts from 0 up to (not including) that number, a shorthand for the classic counted for loop.

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

range-over-func: custom iterators (Go 1.23)

A function can be ranged over if it matches one of the shapes func(yield func() bool), func(yield func(V) bool), or func(yield func(K, V) bool). Inside, you call yield with each value to produce; yield returns false if the loop stopped early (a break), letting the iterator clean up.

Gocustom_iterator.go
func Evens(max int) func(func(int) bool) {
    return func(yield func(int) bool) {
        for i := 0; i < max; i += 2 {
            if !yield(i) {
                return   // consumer broke out of the loop early
            }
        }
    }
}

for n := range Evens(10) {
    fmt.Println(n)   // 0, 2, 4, 6, 8
    if n == 4 {
        break   // yield(6) would return false here
    }
}

The new iter package and standard library support

Go 1.23 added the iter package, defining the standard iter.Seq[V] and iter.Seq2[K, V] function types for iterators, and the slices and maps standard library packages gained iterator-returning functions (like maps.Keys, slices.Values) that plug directly into range-over-func, so custom collection types can now support idiomatic for range without exposing their internals as a slice first.

Sources

1
The Go Authors. "Range Over Function Types", go.dev/blog/range-functions, and the iter package documentation, pkg.go.dev/iter.