Get AI summaries of any video or article — Sign up free
Go 1.23 Released thumbnail

Go 1.23 Released

The PrimeTime·
5 min read

Based on The PrimeTime's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.

TL;DR

Go 1.23 formalizes “range over function,” allowing `for ... range` to accept iterator functions that generate iteration values.

Briefing

Go 1.23 lands about six months after Go 1.22 with a release focus on tooling and library runtime changes—while keeping the “go1 promise” that existing Go programs should keep compiling and running. The biggest language-facing shift is a new capability for `for`-range loops: the range clause now accepts iterator functions, effectively turning the range syntax into a more general iteration mechanism.

For years, Go’s range semantics have been a source of both convenience and confusion. A long-standing “bug” became a feature: ranging over a slice or array reused the same loop variable memory, so taking the address of the iteration variable could lead to surprising results. Go 1.22 introduced an experiment (via a new range-over-function behavior) that avoids that pitfall by using fresh memory locations per iteration, preventing the variable from changing “underneath” code that references it. In Go 1.23, the experiment becomes part of the language: range-over-function is now official.

Under the new model, iterator functions supply iteration values to a `for ... range` loop. The transcript walks through building an iterator-style function using `yield` as the callback that produces each iteration value. The practical takeaway is that the loop no longer needs only built-in rangeable forms like slices, maps, or strings; it can consume iterator functions that follow the expected shape, producing values until the iterator ends. The discussion also highlights why this design feels unusual to some developers: the iterator’s control flow depends on the callback/yield pattern, rather than a more familiar `Next()`-style interface that stores state inside an object.

Beyond iteration, Go 1.23 adds a steady stream of library and tooling improvements. The `go` toolchain gains “Go Telemetry,” collecting usage and break statistics to help the Go team understand how the toolchain is used and where it fails. The transcript emphasizes that telemetry is opt-in, and frames the controversy as largely about privacy and consent—contrasting it with ecosystems where telemetry is effectively required to use features.

Tooling ergonomics also improve: `go env` can now print only settings whose effective values differ from defaults, `go mod tidy` can emit a unified diff without modifying files, and `go list -m -json` includes a new `Sum` field. Static analysis tightens with `go vet` gaining a “Standard Version analyzer” that flags references to symbols introduced after the module’s declared Go version. Runtime and performance tweaks include better trace recovery for partially broken traces, improved indentation for runtime tracebacks, and reduced build-time overhead for profile-guided optimization.

Finally, the release expands iterator-centric library support: new `iter`-related packages and functions (including iterator-aware slice/map helpers) aim to make it easier to transform and consume sequences without manual loops. The overall message: Go 1.23 keeps compatibility, but pushes iteration and tooling forward—especially by making range syntax capable of driving iterator functions in a way that could unlock more expressive, reusable iteration patterns.

Cornell Notes

Go 1.23 formalizes “range over function” so `for ... range` can consume iterator functions, not just built-in rangeable types. The change builds on earlier work that addressed a notorious range-variable pitfall by ensuring iteration variables don’t unexpectedly share the same memory across loop iterations. Iterator functions produce values via a callback-style `yield`, which some developers find less intuitive than a `Next()` interface but offers a straightforward compilation model. The release also adds opt-in Go Telemetry to collect toolchain usage and break statistics, plus multiple tooling and library improvements (module tooling diffs, vet version checks, trace/runtime tweaks, and iterator-friendly helpers).

What new language capability does Go 1.23 add to `for`-range loops, and why does it matter?

Go 1.23 makes the “range over function” experiment part of the language. The `range` clause in a `for`-range loop can now accept iterator functions of specific types; calling the iterator produces iteration values for the loop. This matters because it generalizes Go’s iteration syntax beyond slices/maps/strings, enabling custom iteration sources while keeping the familiar `for ... range` structure.

How does Go 1.23 relate to the long-standing range-variable memory issue?

The transcript references a long-standing behavior where a `for`-range loop could reuse the same memory for the iteration variable, so referencing that variable could observe changes “underneath” the code. Go 1.22 introduced an experiment (described as using new memory locations per iteration) to avoid that surprise. Go 1.23 incorporates the experiment so the safer behavior is now part of the language’s range-over-function story.

What does an iterator function look like in practice under the new range-over-function model?

The walkthrough constructs an iterator-style function that returns a function which accepts a callback named `yield`. The iterator then loops over a collection and calls `yield` for each produced value. In the transcript’s example, the developer ranges over the iterator output and also experiments with reverse iteration (using a decreasing index), showing that the loop consumes values produced by the iterator until completion.

Why do some developers dislike the callback/yield iterator style compared with a `Next()` interface?

The transcript argues that a `Next()`-style iterator interface would keep state inside an object and let the loop repeatedly pull values, which feels more natural. With `yield`, the iterator’s control flow depends on the callback and the loop’s termination behavior is tied to how the callback signals break/stop, which can feel confusing—especially compared with existing Go patterns like `io.Writer`, which uses a method-based interface rather than a callback.

What is Go Telemetry in Go 1.23, and what consent model is emphasized?

Starting in Go 1.23, the Go toolchain can collect usage and break statistics, described as “Go Telemetry,” to help the Go team understand how the toolchain is used and where it breaks. The transcript stresses that telemetry is opt-in and frames the main concern as consent and privacy; it contrasts this with tooling ecosystems where telemetry is effectively required to use features.

Which tooling changes stand out in the transcript, and what problems do they solve?

Several developer-experience improvements are highlighted: `go env` can print only settings whose effective values differ from defaults; `go mod tidy` can output changes as a unified diff without modifying files; `go list -m -json` includes a new `Sum` field; and `go vet` gains a Standard Version analyzer that flags references to symbols introduced after the module’s declared Go version. Together these aim to make configuration, dependency maintenance, and version correctness easier to inspect and debug.

Review Questions

  1. How does range-over-function change what kinds of things can appear on the right-hand side of a `for ... range` clause in Go 1.23?
  2. What range-variable behavior was problematic historically, and how does the newer approach avoid the surprise described in the transcript?
  3. Why might a callback/yield iterator feel less intuitive than a pull-based `Next()` iterator interface, even if it compiles efficiently?

Key Points

  1. 1

    Go 1.23 formalizes “range over function,” allowing `for ... range` to accept iterator functions that generate iteration values.

  2. 2

    The range-over-function work builds on earlier changes intended to prevent the iteration-variable memory pitfall where values could appear to change unexpectedly during the loop.

  3. 3

    Iterator functions in the new model produce values through a callback-style `yield`, which some developers find conceptually awkward compared with `Next()`-style iterators.

  4. 4

    Go Telemetry is introduced as opt-in toolchain usage and break-statistics collection to improve the Go toolchain over time.

  5. 5

    Go tooling gains more inspectable workflows: `go env` can show only non-default effective settings, and `go mod tidy` can emit a unified diff without editing files.

  6. 6

    `go vet` adds a Standard Version analyzer to catch references to symbols that are newer than the module’s declared Go version.

  7. 7

    Library support expands around iterators, including iterator-aware helpers for transforming and consuming sequences (e.g., collecting into slices or maps).

Highlights

Go 1.23 makes iterator functions a first-class input to `for ... range`, turning range syntax into a general iteration driver.
The release incorporates earlier range-over-function behavior meant to avoid the classic “range variable memory reuse” surprise.
Opt-in Go Telemetry arrives to measure toolchain usage and failures, with the transcript framing consent as the key issue.
`go mod tidy` can now print changes as a unified diff without modifying files, improving reviewability of dependency updates.

Topics

  • Go 1.23 Release Notes
  • Range Over Function
  • Iterator Functions
  • Go Telemetry
  • Go Toolchain Updates