languages
March 21, 2026 · 2 min read · 4 views

Go 1.23: Iterators and Range-Over Func Syntax

Go 1.23 stabilizes iterator support and range-over functions, simplifying loop patterns and improving code readability for developers.

What’s New in Go 1.23

Go 1.23, released in September 2024, brings one of the most significant language changes in recent years: full support for iterators through the range statement. This update stabilizes the range-over func feature that was introduced experimentally in Go 1.22, making it a first-class language construct.

Range-Over Functions Explained

Previously, iterating over custom collections required either explicit indexing or callback patterns. Go 1.23 lets you write iterator functions that work naturally with range:

func counter(max int) func(func(int) bool) bool {
    return func(yield func(int) bool) bool {
        for i := 0; i < max; i++ {
            if !yield(i) {
                return false
            }
        }
        return true
    }
}

// Now you can use it intuitively:
for i := range counter(10) {
    fmt.Println(i)
}

The iterator protocol uses a yield function that returns false when the loop breaks, allowing clean early exit handling without goroutines or channels.

Key Improvements

Simpler custom iterators: Libraries can now provide cleaner APIs for traversing data structures. Previously, you’d implement for/range using slices or channels; now iterators are lightweight and efficient.

Better performance: No heap allocation overhead like channels require. Iterators compile down to simple loops under the hood.

Cleaner standard library: Go’s iter package provides Seq and Seq2 types for single and key-value pairs, making iterator signatures explicit and consistent.

Practical Example

Consider iterating over a tree structure:

func (n *Node) All(yield func(*Node) bool) bool {
    if !yield(n) {
        return false
    }
    if n.left != nil && !n.left.All(yield) {
        return false
    }
    if n.right != nil && !n.right.All(yield) {
        return false
    }
    return true
}

// Usage:
for node := range tree.All {
    process(node)
}

Before, you’d likely use channels or maintain manual recursion state. This is far more readable and performant.

Other Notable Changes

  • Range-over int: You can now for i := range n for numeric ranges without creating a slice.
  • Improved toolchain: Better error messages and diagnostics for common mistakes.
  • PGO enhancements: Profile-guided optimization now covers more scenarios for production workloads.

If you’re working with complex configuration or data formats, the JSON Formatter and YAML/JSON Converter can help validate iterator outputs during testing.

Why It Matters

This release closes a long-standing gap in Go’s expressiveness. Before 1.23, custom iteration patterns often felt awkward compared to higher-level languages. Range-over functions make Go code more intuitive without sacrificing performance—a win for readability and maintainability in large codebases.

The stabilization also signals Go’s confidence in the design; this isn’t experimental anymore. Teams can safely adopt these patterns in production code.

What to Do Next

  1. Update your Go toolchain to 1.23+ if you manage custom data structures.
  2. Refactor existing iterators using callbacks or channels to the new range syntax.
  3. Review third-party libraries — popular packages will likely adopt this pattern in upcoming releases.
  4. Test thoroughly — while the feature is stable, migrating code requires validation that behavior remains identical.
This post was generated with AI assistance and reviewed for accuracy.

Sponsored Links

Advertisements

Upgrade to Kloubot Pro

Ad-free experience, unlimited history, file exports & more — $5/mo

Go Pro