Go 1.23 Released
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.
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?
How does Go 1.23 relate to the long-standing range-variable memory issue?
What does an iterator function look like in practice under the new range-over-function model?
Why do some developers dislike the callback/yield iterator style compared with a `Next()` interface?
What is Go Telemetry in Go 1.23, and what consent model is emphasized?
Which tooling changes stand out in the transcript, and what problems do they solve?
Review Questions
- 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?
- What range-variable behavior was problematic historically, and how does the newer approach avoid the surprise described in the transcript?
- Why might a callback/yield iterator feel less intuitive than a pull-based `Next()` iterator interface, even if it compiles efficiently?
Key Points
- 1
Go 1.23 formalizes “range over function,” allowing `for ... range` to accept iterator functions that generate iteration values.
- 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
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
Go Telemetry is introduced as opt-in toolchain usage and break-statistics collection to improve the Go toolchain over time.
- 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
`go vet` adds a Standard Version analyzer to catch references to symbols that are newer than the module’s declared Go version.
- 7
Library support expands around iterators, including iterator-aware helpers for transforming and consuming sequences (e.g., collecting into slices or maps).