Stable Release in branch 1.21
1.21.13
Released 06 Aug 2024
(1 year ago)
SoftwareGo
Version1.21
Status
End of life
Initial release1.21.0
08 Aug 2023
(2 years ago)
Latest release1.21.13
06 Aug 2024
(1 year ago)
End of life13 Aug 2024
(Ended 1 year ago)
Release noteshttps://go.dev/doc/go1.21
Source codehttps://github.com/golang/go/tree/go1.21.13
Documentationhttps://go.dev/doc/
Go 1.21 ReleasesView full list

What Is New in Go 1.21

Go 1.21 brings significant enhancements to the toolchain, standard library, and language itself. This release focuses on improving developer productivity, code clarity, and performance.

Category Key Changes
Language Changes New built-in functions (min, max, clear), type inference for generic functions, and improved type checking.
Tooling Structured profile-guided optimization (PGO), improved linker, and better backtrace information.
Standard Library New slices, maps, and cmp packages. Updates to the log/slog package and HTTP routing.
Ports Support for WASI preview1 and FreeBSD on RISC-V (riscv64).
Performance Compiler optimizations, memory management improvements, and faster builds.

What new built-in functions were added?

Go 1.21 introduces three new built-in functions: min, max, and clear. The min and max functions compare ordered values, returning the smallest or largest argument, respectively. This is handy for writing concise bounds-checking and comparison logic without helper functions.

The clear function removes all elements from a map or sets all elements of a slice to the zero value. For maps, it's equivalent to a loop that deletes every key. For slices, it zeroes the elements from index 0 to len(s)-1. This provides a clear and efficient way to reset these data structures.

// Example using the new built-ins
m := map[string]int{"a": 1, "b": 2}
clear(m) // m is now an empty map: map[]

s := []int{1, 2, 3, 4}
clear(s) // s is now []int{0, 0, 0, 0}

x := min(10, 5, 25) // x == 5
y := max(10, 5, 25) // y == 25

How does Profile-Guided Optimization work now?

Profile-Guided Optimization (PGO) is now fully integrated and stable in Go 1.21. You provide the compiler with a CPU profile from a previous run of your application, and it uses that data to guide its optimization decisions. This typically results in performance improvements of 2-7% for real-world workloads.

In practice, you build your binary with the -pgo flag pointing to a .pprof file. The compiler analyzes hot code paths and inlining decisions based on actual usage patterns, not just static analysis. This matters because it tailors optimizations to your specific application's behavior.

# Build with PGO
go build -pgo=auto cmd/myapp

# With auto, the compiler looks for a default.pgo file in the main package directory
# Or specify a specific profile
go build -pgo=./cpu.pprof cmd/myapp

What are the new generic slices and maps packages?

The new slices and maps packages provide generic functions for working with slices and maps of any element type. They eliminate the need to write repetitive boilerplate code for common operations like sorting, searching, comparing, and manipulating collections.

The slices package includes functions for cloning, sorting, binary search, and checking for containment. The maps package offers utilities for copying, retrieving keys, and comparing maps. These packages feel like a natural extension of the language's generic capabilities introduced in earlier versions.

import "slices"

func main() {
    s := []int{3, 1, 4, 1, 5}
    sorted := slices.Sort(s)       // [1, 1, 3, 4, 5]
    hasFive := slices.Contains(s, 5) // true
    cloned := slices.Clone(s)
}

How has the logging improved with slog?

The log/slog package, which was experimental in Go 1.20, is now stable in Go 1.21. It provides structured logging with levels, key-value attributes, and pluggable handlers for output formats like JSON and text. This is a significant upgrade from the standard log package for production systems.

You can easily attach contextual information to log lines, which is crucial for debugging complex applications. Handlers can be customized to output logs in different formats, making it easier to integrate with log aggregation systems. The API is designed to be both simple for basic use cases and extensible for advanced needs.

import "log/slog"

logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
logger.Info("user logged in",
    "user_id", 12345,
    "ip", "192.168.1.1",
)
// Outputs: {"time":"...","level":"INFO","msg":"user logged in","user_id":12345,"ip":"192.168.1.1"}

FAQ

Is the `slog` package backward compatible with the old `log` package?
Not directly. The `log/slog` package has a different API focused on structured logging. However, you can use the `slog.NewLogLogger` function to create a `slog.Logger` that implements the `log.Logger` interface, allowing for a gradual migration.

Do I have to use PGO to get good performance?
No. The standard compiler optimizations are still excellent. PGO provides an additional, optional performance boost by tailoring optimizations to your specific application's execution profile.

What happens if I call `clear` on a nil map or slice?
Calling `clear` on a nil map is a no-op-it does nothing. Calling `clear` on a nil slice panics, just like any other operation that tries to access the length of a nil slice.

Are the new `slices` and `maps` packages meant to replace the standard ways of working with them?
They are meant to complement them. For simple operations, using language built-ins is fine. For more complex operations like sorting or deep comparisons, the new generic packages are the recommended approach.

Does the improved linker make a noticeable difference in build times?
Yes, especially for larger applications. The linker improvements, combined with other optimizations, contribute to faster overall build times, which is a big win for developer productivity in large codebases.

Releases In Branch 1.21

VersionRelease date
1.21.1306 Aug 2024
(1 year ago)
1.21.1202 Jul 2024
(2 years ago)
1.21.1104 Jun 2024
(2 years ago)
1.21.1007 May 2024
(2 years ago)
1.21.903 Apr 2024
(2 years ago)
1.21.805 Mar 2024
(2 years ago)
1.21.706 Feb 2024
(2 years ago)
1.21.609 Jan 2024
(2 years ago)
1.21.505 Dec 2023
(2 years ago)
1.21.407 Nov 2023
(2 years ago)
1.21.310 Oct 2023
(2 years ago)
1.21.205 Oct 2023
(2 years ago)
1.21.106 Sep 2023
(2 years ago)
1.21.008 Aug 2023
(2 years ago)
1.21rc402 Aug 2023
(2 years ago)
1.21rc314 Jul 2023
(2 years ago)
1.21rc221 Jun 2023
(3 years ago)
1.21rc116 Jun 2023
(3 years ago)