Back to JetBrains

Go 1.26 Release Party

JetBrainsFebruary 19, 20261h 38m
In a Nutshell

Go 1.26 introduces major features including a new built-in expression that allocates and initializes in one step, `errors.AsType[T]` for compile-time safe error type checking, and the "green tea" garbage collector that reduces CPU cache misses for 5%+ gains on small-object workloads. The release adds production-ready goroutine leak detection via `runtime/pprof`, `runtime/secret` for cryptographic memory clearing, `slog` multi-handlers, iterator methods across `reflect`, and `go fix` for automatic modernization. Performance improvements double I/O throughput, while new runtime metrics and `bytes.Buffer.Peek` enhance observability and buffer handling.

AI-Generated Notes

These notes were generated by AI and may contain inaccuracies.

The Go 1.26 live stream celebrates the release of the new version of the language. The moderator admits to knowing only how Go is spelled and will rely on two experts to carry the discussion. The audience is invited to share their favorite features from Go 1.26 in the chat.

Alex Hughes is a software engineer from Brazil working in leadership roles, participating in conferences and workshops, and writing books about Go. Anton works with Go both professionally and in his free time, preparing interactive tours for Go releases over the past few years.

Alex identifies type checking for errors as his favorite feature, noting Go now has an error as type concept. Anton highlights four features: goroutine leak detection (experimental), the new cmd capability in Go, performance improvements including I/O doubling in performance, and the ability to identify the cause of a signal cancellation for troubleshooting and debugging.

The release is referred to as Go 1.26. The stream is recorded and will be available on YouTube afterward. A giveaway includes a six-month extended GoLand trial using the code "go release party." GoLand 1.26 support was prepared in the latest version. Anton describes Go 1.26 as the biggest release seen, with the sheer number of features packed into it being astonishing.

The new built-in previously allocated a variable of a specific type and required separate assignment. In Go 1.26, new accepts any expression including specific values, structs, or function call results. The Go runtime allocates the variable, assigns the value, and returns a pointer. This is particularly useful for structs with optional fields used in JSON or protobuf serialization. Projects with helper functions like ptr can now delete these helpers and use the new built-in directly.

The errors.As function previously required declaring a target variable before calling, then checking a boolean result. The new errors.AsType generic function takes an error type as a generic parameter and the error value as a regular parameter, scoping variables to if branches. When checking multiple errors like operation errors, DNS errors, or other errors, each variable remains scoped to its branch. The construction resembles a switch statement for errors, which cannot use regular switch due to wrapping. Errors.AsType is more type-safe than errors.As since it checks at compile time whether the type implements the error interface. The function is faster, allocates less, and does not use the reflect package. The Go team recommends using errors.AsType instead of errors.As going forward.

Go has a single garbage collector that works well without configuration. The old collector was a mark-and-sweep implementation that jumped across heap memory regions, causing CPU cache misses where the CPU spent up to 35% of garbage collection time waiting for memory. The Go runtime allocator uses spans, which are linear 8-kilobyte blocks split into equal slots. The new "green tea" garbage collector works with spans so objects are located adjacent to each other, allowing the CPU to load chunks containing multiple objects. This reduces cache misses and improves efficiency. Average applications may see marginal improvements, but applications allocating many small objects may see approximately 5% reduction in overall CPU usage. The green tea collector is enabled by default and the old collector can be temporarily switched back, though this option will be removed in future releases.

The go fix command modernizes code using the same backend as go vet, with both using the analysis framework. Go vet identifies potential problems while go fix automatically rewrites code to use modern language and standard library features. All changes are considered safe by the Go team. Users can run go fix on packages and optionally specify which analyzers to run. An example refactoring converts manual sync.WaitGroup counter manipulation using Add and Done methods to the modern go method. GoLand is expected to support these refactorings soon. The Go team indicates it will become easier to create custom analyzers for specific projects. An interactive tour of the Go 1.26 release is available at a provided link.

A question about whether Rust's increase in cloud applications influenced the Go 1.26 garbage collector was addressed by noting the main influence is modern computing with servers having many cores, making the old cache-miss-heavy design inefficient for 64-core machines. The garbage collector improvements target high-performance computing scenarios. For applications creating millions of objects per minute where older objects are deleted, the new collector may help if objects go to the heap rather than the stack and are small (under half a kilobyte). Experimental vectorized operations in Go 1.26 support only AMD64 platforms, not ARM or RISC-V yet. The Go team wants feedback from developers using SIMD vectorized operations on AMD64 before expanding platform support.

The Go team is seeking feedback from developers using SIMD vectorized operations on ARM64 and AMD64 platforms. Based on this feedback, the team plans to broaden support for these operations across other platforms in future releases.

A new feature called secret mode was introduced, related to cryptography. The runtime/secret package provides a single Do function that accepts an anonymous function. When execution leaves the scope of this function, the runtime automatically clears CPU registers and stack variables allocated within the secret.Do scope.

For heap-allocated variables within the secret.Do block, the garbage collector zeros out memory as soon as variables become unreachable. This differs from standard memory freeing, which only marks memory as available for reuse—the secret mode actually zeros out the data, making old information inaccessible.

This feature addresses security requirements in modern cryptographic protocols where session keys are derived from temporary keys. Without secret mode, temporary private keys and shared secrets would remain in memory after use, potentially allowing attackers to derive session keys and decrypt past sessions even if private keys are later leaked.

The secret.Do function guarantees that temporary variables are zeroed upon leaving scope. The session key itself is not cleared while the session is active, but will be zeroed by the garbage collector once it becomes unreachable after the session ends.

This feature is primarily intended for cryptographic library developers rather than regular application developers.

Goroutine leaks occur when a goroutine becomes stuck on a synchronization object like a channel while other goroutines continue executing normally. This situation leaks resources and eventually impacts application performance.

Unlike deadlocks (which cause panics with stack traces) or data races (detectable via the race detector), goroutine leaks remained difficult to detect until Go 1.25 introduced the synctest package for testing environments.

Go 1.26 introduces production-ready goroutine leak detection through the runtime/pprof package. The runtime/pprof.Lookup function now supports a "goroutineleak" profile that identifies leaked goroutines and provides specific line numbers where leaks occur.

The feature is marked experimental only due to API convenience considerations—the underlying algorithm is production-ready. The Go team encourages production usage to gather feedback on the API design.

Go 1.26 adds new runtime metrics specifically for goroutine states. Previously, only the total count of live goroutines was available. New metrics track:

  • Number of goroutines executing system calls or segfaults
  • Number of runnable but not currently running goroutines
  • Number of currently executing goroutines
  • Number of goroutines waiting on synchronization objects

These metrics enable early problem detection before issues manifest in logs or user complaints. For example, steadily increasing runnable goroutine counts may indicate excessive load or bugs creating unnecessary goroutines.

A new metric for the total number of live threads was also added.

Iterators continue to spread throughout the standard library. New iterator methods in the reflect package include:

  • reflect.Type.Fields() - iterates over struct fields
  • reflect.Type.Methods() - iterates over methods
  • reflect.Type.In() and reflect.Type.Out() - iterate over function input/output parameters

These can be used with for range loops, replacing older explicit looping patterns.

The log/slog package now includes a multi-handler that routes log records to multiple destinations simultaneously. Previously, logging to both stdout and files required workarounds like io.MultiWriter with their associated complications.

The multi-handler wraps any number of handlers and distributes each log record to all wrapped handlers, enabling simultaneous logging to different outputs (e.g., stdout in text format and files in JSON format).

A new Peek method was added to bytes.Buffer that allows viewing bytes without advancing the buffer position. Unlike Read, Peek returns a slice that provides a view into the buffer's underlying data rather than a copy.

This means modifications to the peeked slice directly affect the buffer contents. The implementation returns the actual bytes from the buffer, not a duplicate.

The fmt.Errorf function was optimized to match the performance and allocation characteristics of errors.New when creating unformatted error strings. The implementation checks whether the format string contains a percent symbol—if not, it immediately delegates to errors.New, avoiding unnecessary formatting machinery.

This eliminates the previous performance gap where errors.New was marginally faster and allocated less memory than fmt.Errorf for plain error strings.

When memory is allocated but never freed, this constitutes a memory leak independent of secret mode functionality. Secret mode only zeros memory after the garbage collector determines the data is unreachable—first unreachable, then zeroed.

A service health checker application was used to demonstrate migration from Go 1.25 to Go 1.26. The process involves updating the Go version specification and using IDE tooling that provides syntax analysis suggestions and highlights of new features.

The IDE integration includes links to proposal documents, change histories, commit information, and official documentation. A tutorial mode allows experimenting with new features in temporary projects that can be reset if needed.

The syntax analysis feature can process an entire project or monorepo. In this non-monorepo project, the module achieves the same effect. The analyzer panel shows 11 syntax updates in total. The summary indicates fixes for pointer creation of new and type unwrapping using errors as type. Fixes can be applied directly to files or all at once across three files with eight problems found. Caution is advised when applying fixes to generated code, as it should respect the original generation process.

When reviewing the main file, consideration is needed to determine if fixes are part of the intended changes. For status code and timeout modifications, applying fixes across all elements in the list is acceptable. Similar concerns apply to timeouts being modernized with new expression functions, making it reasonable to apply fixes for every identified problem.

The checker identifies several instances of errors being translated for type. These fixes are applied blindly because they represent objectively better code. The codebase fixes are completed through two categories of fixes. After reviewing changes in the commit panel, the modifications make sense.

Not all fixes are available immediately, so go fix can be executed manually. M taskus is preferred over make files for task control and version management. The first difference caught involves using sort from the package sort, modernized to use slices to sort. The second difference involves split being duplicated, recommending split sec of sequence instead. For range operations, integer ranging eliminates the need for C-style for loops for simple operations.

Go fix is a reliable, deterministic tool rather than stochastic like LLMs. The recommendation is to understand the changes before applying fixes. The syntax updates for Go 1.26 are now complete.

Benchmarks are inherently variable due to machine noise, iteration counts, and other factors affecting results. The benchmark creates a test server to receive requests, emulating remote targets. A new checker is created with 500 checkers for the same backend URL and no logger, as logging adds noise. The first run warms the map, as single-run benchmarks with cold machines are unreliable. GC pressure is intentionally created, and the history of checks is preserved in an array to prevent compiler optimization.

Benchmarks run against the original Go 1.24.26 with green team settings using the experimental old version, compared with bench stats for statistical relevance. The application example involves a home server checking torrent availability.

For simple applications or single-instance machines without Kubernetes, Grafana, or similar tooling, logs should write to stdout via a text handler. A flight recorder concept from Grafana is adapted, creating a ring buffer for profiles that rotates when full. The goal is to maintain both stdout capability and ring buffer functionality without duplicating text and JSON writing.

A pet project program mimics the flight recorder but records logs instead of profiler metrics. The library import is named log flight recorder. Dependencies are resolved through context actions and go mod tidy running in the background. The go.mod file automatically updates with the new dependency.

A multi-handler enables multiple handlers simultaneously. The existing text handler is extracted and named text handler. Using the multi-handler without changing program behavior maintains existing functionality. The log recorder offers options for buffer retention, with five being a simple starting point.

Live templates accelerate handler creation, particularly for logs. A debug logs template and JSON template eliminate manual copying. The log recorder is accessed to display the latest five entries. ResponseWriter serves as the writer for log output, with error handling implemented. Writing only to headers creates a problem with logger access, avoiding circular dependencies.

The application runs on Go 1.26. Main function execution requires configuration verification. Live templates also facilitate handler function creation with content type specification.

Development efforts should focus on tasks requiring deeper thinking rather than routine, delegable tasks. For debug metrics suitable for home servers but not enterprise settings using Prometheus or OpenTelemetry collectors, AI delegation is preferred. Journey is used to implement endpoints without extensive planning for small features.

Quality comments and TODOs are essential for Journey's success. For simple tasks, autonomous LLM behavior is preferred over restricted prompts like "do not run tests" or "do not assert things." The diff shows important metrics implementation instead of TODO comments.

AI can generate code that works well and maintains modern Go 1.26 syntax. The new config method in config.go is implemented, with AI using modern patterns rather than 2018-era approaches. Error handling uses errors.Is and errors.As patterns.

Claude initially produces suboptimal error status implementations. The Go Modern Guidelines plugin from JetBrains GitHub repository provides Go modernization capabilities equivalent to Journey when used with Claude Code. Plugin installation involves simple steps, followed by enabling and restarting the IDE.

After enabling the Go modern plugin, Claude produces improved error status implementations using modern patterns. The plugin enables preferred tools while maintaining Go 1.26 code quality standards.

Keep JetBrains in your library

Save the videos and channels worth coming back to, and find them again in one place.