Go 1 23

Overview

Go 1.23, released in August 2024, introduces iterator functions that enable custom iteration patterns with for-range loops, a unique package for efficient value deduplication, and important timer behavior improvements.

Key Features

Iterator Functions

Range over custom iteration patterns:

// Iterator function
func Count(n int) func(func(int) bool) {
    return func(yield func(int) bool) {
        for i := 0; i < n; i++ {
            if !yield(i) {
                return
            }
        }
    }
}

// Range over iterator
for i := range Count(5) {
    fmt.Println(i)  // 0, 1, 2, 3, 4
}

Using iter.Seq types:

import "iter"

func Fibonacci(max int) iter.Seq[int] {
    return func(yield func(int) bool) {
        a, b := 0, 1
        for a <= max {
            if !yield(a) {
                return
            }
            a, b = b, a+b
        }
    }
}

for n := range Fibonacci(100) {
    fmt.Println(n)  // 0, 1, 1, 2, 3, 5, 8, 13, ...
}

unique Package

Value canonicalization for memory optimization:

import "unique"

// Canonicalize values
h1 := unique.Make("hello")
h2 := unique.Make("hello")

fmt.Println(h1 == h2)  // true (same Handle, shares storage)

// Use case: String interning
type Logger struct {
    messages []unique.Handle[string]
}

func (l *Logger) Log(message string) {
    l.messages = append(l.messages, unique.Make(message))
    // Repeated strings share storage
}

Timer Behavior Improvements

Unbuffered channels: Timer channels now have capacity 0, preventing race conditions.

GC-eligible timers: Unreferenced timers are automatically garbage collected:

func createTimer() {
    timer := time.NewTimer(time.Hour)
    // Timer becomes unreachable - GC reclaims it
    // No explicit Stop() needed for GC
}

slices and maps Iterator Functions

import "slices"

s := []string{"a", "b", "c"}

// Iterate with index
for i, v := range slices.All(s) {
    fmt.Printf("%d: %s\n", i, v)
}

// Values only
for v := range slices.Values(s) {
    fmt.Println(v)
}

// Backward iteration
for i, v := range slices.Backward(s) {
    fmt.Printf("%d: %s\n", i, v)  // 2: c, 1: b, 0: a
}

References


Last Updated: 2026-02-04 Go Version: 1.23+ (stable), 1.25.x (latest stable)

Last updated