Archive · Week 28 · Jul 7 – 13, 2025from 6 items
This week the Go team accepted three proposals that extend the standard library, released two patch‑level point releases, and published a blog post on generic interfaces. The accepted proposals add new SSH callback hooks, hashing helpers for the type checker, and an “omitzero” XML tag. The releases focus on security and bug fixes, while the blog highlights the power of type parameters on interfaces.
Breakingtooling
go1.23.11 released
- What changed
- The release includes security fixes to the
gocommand and bug fixes to the compiler, linker, and runtime. - Production impact
- The source does not say.
- Try it
- Run
go versionto confirm the new version andgo envto check the updated toolchain. - Source
- go.dev/doc/devel/release#go1.23.11
Explain it and run it
Understand it, then run it
Go 1.23.11 was released on 2024‑10‑??. The release contains only security and bug fixes. No new language features or APIs were added. The change is a maintenance update that keeps the toolchain safe and stable.
Run it now
// This program runs on Go 1.27.1 and demonstrates that the 1.23.11 release
// contains only security and bug fixes, with no new language features.
package main
import "fmt"
func main() {
fmt.Println("No new language features were added in 1.23.11.")
}
What it printed when we ran it on Go 1.27.1
No new language features were added in 1.23.11.
Run sends this program (for Solidity, the contract and its tests) to our own sandbox, where it is compiled and run once, with no network, and what it printed or the test report comes back here. Nothing is kept. Runs are counted per visitor for the day so everyone gets a turn; the details are on the legal page.
Breakingtooling
go1.24.5 released
- What changed
- The release includes security fixes to the
gocommand and bug fixes to the compiler, linker, runtime, and thegocommand itself. - Production impact
- The source does not say.
- Try it
- Update your Go installation to 1.24.5 and run
go test ./...to ensure existing tests still pass. - Source
- go.dev/doc/devel/release#go1.24.5
Explain it and run it
Understand it, then run it
Go 1.24.5 was released on 2025‑07‑08. It contains security fixes for the go command and bug fixes for the compiler, linker, runtime, and the go command itself. No new language features or APIs were added. The change is a maintenance release that improves the reliability and safety of the toolchain.
Run it now
// This program demonstrates that the Go 1.24.5 toolchain compiles and runs correctly.
// It simply prints a message to confirm the environment is functional.
package main
import "fmt"
func main() {
fmt.Println("Go 1.24.5 toolchain is working")
}
What it printed when we ran it on Go 1.27.1
Go 1.24.5 toolchain is working
Run sends this program (for Solidity, the contract and its tests) to our own sandbox, where it is compiled and run once, with no network, and what it printed or the test report comes back here. Nothing is kept. Runs are counted per visitor for the day so everyone gets a turn; the details are on the legal page.
Worth knowingstdlib
x/crypto/ssh: verified public key callback and arbitrary data in Permissions
- What changed
- The
ServerConfigtype now includes aVerifiedPublicKeyCallbackfield that is invoked after a client successfully proves control over a key previously approved byPublicKeyCallback. The callback receives thePermissionsobject returned byPublicKeyCallbackand may return a modified or newPermissionsobject.PublicKeyCallbackis no longer allowed to return aPartialSuccessError; that error can only be returned byVerifiedPublicKeyCallback. - Production impact
- The source does not say.
- Try it
- Create a
ServerConfigwith both callbacks and observe the order of invocation during a key‑based SSH session. - Source
- github.com/golang/go/issues/70795
Explain it and run it
Understand it, then run it
The SSH package lets a server decide whether a client can log in with a public key. Previously the only hook was PublicKeyCallback, which ran before the client sent a signature. Now a new optional hook, VerifiedPublicKeyCallback, runs after the client proves it owns the key. It receives the same Permissions object that PublicKeyCallback returned and can modify or replace it. PublicKeyCallback can no longer return a PartialSuccessError; that error is now only allowed from VerifiedPublicKeyCallback.
Run it now
// This program demonstrates the intended behaviour of the new
// `VerifiedPublicKeyCallback` and the `ExtraData` field in `Permissions`.
// Since the change is not yet in Go 1.27.1, the code below uses mock
// types that mimic the relevant parts of golang.org/x/crypto/ssh.
// Running this program prints the sequence of callbacks and the
// data passed between them.
package main
import (
"fmt"
)
// Mock types that resemble the real ssh package structures.
type ConnMetadata struct{ ID int }
type PublicKey struct{ Key string }
type Permissions struct {
CriticalOptions map[string]string
Extensions map[string]string
ExtraData any
}
type PartialSuccessError struct{ msg string }
func (e *PartialSuccessError) Error() string { return e.msg }
// ServerConfig holds the callbacks.
type ServerConfig struct {
PublicKeyCallback func(ConnMetadata, PublicKey) (*Permissions, error)
VerifiedPublicKeyCallback func(ConnMetadata, PublicKey, *Permissions) (*Permissions, error)
}
// Simulate an SSH handshake that triggers the callbacks.
func simulateHandshake(cfg ServerConfig, meta ConnMetadata, key PublicKey) {
// Step 1: PublicKeyCallback is called.
perms, err := cfg.PublicKeyCallback(meta, key)
if err != nil {
fmt.Println("PublicKeyCallback error:", err)
return
}
fmt.Println("PublicKeyCallback returned permissions:", perms)
// Step 2: If a signature is provided (simulated here), call VerifiedPublicKeyCallback.
if cfg.VerifiedPublicKeyCallback != nil {
newPerms, err := cfg.VerifiedPublicKeyCallback(meta, key, perms)
if err != nil {
fmt.Println("VerifiedPublicKeyCallback error:", err)
return
}
fmt.Println("VerifiedPublicKeyCallback returned permissions:", newPerms)
}
}
func main() {
// Define the callbacks.
cfg := ServerConfig{
PublicKeyCallback: func(meta ConnMetadata, key PublicKey) (*Permissions, error) {
// Pretend we decide the key is acceptable and attach some data.
perms := &Permissions{
CriticalOptions: map[string]string{"no-port-forwarding": ""},
Extensions: map[string]string{"permit-agent-forwarding": ""},
ExtraData: fmt.Sprintf("user-%d", meta.ID),
}
return perms, nil
},
VerifiedPublicKeyCallback: func(meta ConnMetadata, key PublicKey, perms *Permissions) (*Permissions, error) {
// Use the data from PublicKeyCallback and modify permissions.
if perms.ExtraData == nil {
return nil, &PartialSuccessError{"missing extra data"}
}
// Append a new critical option based on the extra data.
perms.CriticalOptions["permit-pty"] = ""
return perms, nil
},
}
// Run the simulation.
meta := ConnMetadata{ID: 42}
key := PublicKey{Key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC..."}
simulateHandshake(cfg, meta, key)
}
What it printed when we ran it on Go 1.27.1
PublicKeyCallback returned permissions: &{map[no-port-forwarding:] map[permit-agent-forwarding:] user-42}
VerifiedPublicKeyCallback returned permissions: &{map[no-port-forwarding: permit-pty:] map[permit-agent-forwarding:] user-42}
Run sends this program (for Solidity, the contract and its tests) to our own sandbox, where it is compiled and run once, with no network, and what it printed or the test report comes back here. Nothing is kept. Runs are counted per visitor for the day so everyone gets a turn; the details are on the legal page.
Worth knowingstdlib
encoding/xml: add omitzero option
- What changed
- The
encoding/xmlpackage now supports anomitzerostruct tag option. When marshaling, a field withomitzerois omitted if its value is zero as determined byIsZero()if present, otherwise byreflect.Value.IsZero. The option is ignored during unmarshaling and combines withomitemptyusing logical OR. - Production impact
- The source does not say.
- Try it
- Marshal a struct with a field tagged
xml:"name,omitempty,omitzero"and observe when the field is omitted. - Source
- github.com/golang/go/issues/69857
Explain it and run it
Understand it, then run it
Run it now
// This program demonstrates the new omitzero option in encoding/xml.
// It shows that a field with omitzero is omitted when its value is zero.
// The program runs under Go 1.27.1, which already includes the change.
package main
import (
"encoding/xml"
"fmt"
)
type Example struct {
// The omitzero tag causes this field to be omitted when empty.
Name string `xml:"Name,omitempty,omitzero"`
// A slice that is nil will be omitted, but a zero-length slice will be emitted.
Items []int `xml:"Item,omitempty,omitzero"`
}
func main() {
// Create a value with zero fields.
e := Example{}
// Marshal to XML.
data, err := xml.MarshalIndent(e, "", " ")
if err != nil {
panic(err)
}
// Print the resulting XML. The Name element is omitted because it is zero.
// The Items element is omitted because the slice is nil.
fmt.Println(string(data))
}
What it printed when we ran it on Go 1.27.1
<Example></Example>
Run sends this program (for Solidity, the contract and its tests) to our own sandbox, where it is compiled and run once, with no network, and what it printed or the test report comes back here. Nothing is kept. Runs are counted per visitor for the day so everyone gets a turn; the details are on the legal page.
Nice to knowlanguage
Generic interfaces blog post
- What changed
- The blog explains that adding type parameters to interface types is surprisingly powerful, highlighting new patterns and use cases.
- Production impact
- The source does not say.
- Try it
- Read the blog and experiment with a generic interface in a small program.
- Source
- go.dev/blog/generic-interfaces
Explain it and run it
Understand it, then run it
The Go blog shows that interfaces can now have type parameters. Before this, an interface was just a set of method signatures. With type parameters, an interface can describe a whole family of interfaces, one for each type argument. This lets you write generic code that requires a type to implement a method that takes its own type, such as a Compare method for ordering.
Run it now
// This program demonstrates a generic interface with a type parameter.
// It compiles with Go 1.27.1, which already supports generic interfaces.
package main
import (
"fmt"
"time"
)
// Comparer is a generic interface that requires a Compare method
// accepting a value of the same type.
type Comparer[T any] interface {
Compare(T) int
}
// TimeWrapper wraps time.Time to implement Comparer[TimeWrapper].
type TimeWrapper struct{ t time.Time }
// Compare compares two TimeWrapper values using the underlying time.Time.
func (tw TimeWrapper) Compare(other TimeWrapper) int {
if tw.t.Before(other.t) {
return -1
}
if tw.t.After(other.t) {
return 1
}
return 0
}
// Max returns the larger of two values that satisfy Comparer.
func Max[T Comparer[T]](a, b T) T {
if a.Compare(b) >= 0 {
return a
}
return b
}
func main() {
now := TimeWrapper{t: time.Now()}
earlier := TimeWrapper{t: time.Now().Add(-time.Hour)}
// Max uses the generic Comparer interface to pick the later time.
later := Max(now, earlier)
fmt.Println("Later time:", later.t)
}
What it printed when we ran it on Go 1.27.1
Later time: 2026-10-01 08:46:22.227620274 +0000 UTC m=+0.000043182
Run sends this program (for Solidity, the contract and its tests) to our own sandbox, where it is compiled and run once, with no network, and what it printed or the test report comes back here. Nothing is kept. Runs are counted per visitor for the day so everyone gets a turn; the details are on the legal page.
Exercise
Exercise – Using the new VerifiedPublicKeyCallback and Permissions.ExtraData
Write a small program that demonstrates how the ServerConfig’s PublicKeyCallback can store arbitrary data in the Permissions object and how the VerifiedPublicKeyCallback can read that data and modify the permissions before the SSH handshake completes. The program should:
1. Define a dummy public key and a dummy connection metadata. 2. Call PublicKeyCallback to obtain a Permissions object that contains a custom value in ExtraData. 3. Call VerifiedPublicKeyCallback with the same key and the permissions returned above. 4. Print the final permissions to show that the VerifiedPublicKeyCallback was able to read and modify the data.
The goal is to see the flow of data between the two callbacks, not to actually start an SSH server.
---
package main
import (
"fmt"
)
// Dummy types that mimic the real ssh package.
type ConnMetadata struct{ User string }
type PublicKey struct{ Key string }
// Permissions holds authentication permissions and arbitrary data.
type Permissions struct {
CriticalOptions map[string]string
Extensions map[string]string
ExtraData any
}
// ServerConfig holds the callbacks.
type ServerConfig struct {
PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
VerifiedPublicKeyCallback func(conn ConnMetadata, key PublicKey, permissions *Permissions) (*Permissions, error)
}
func main() {
// The exercise starts here. Your code should go below this line.
}
Show a solution
package main
import (
"fmt"
)
// Dummy types that mimic the real ssh package.
type ConnMetadata struct{ User string }
type PublicKey struct{ Key string }
// Permissions holds authentication permissions and arbitrary data.
type Permissions struct {
CriticalOptions map[string]string
Extensions map[string]string
ExtraData any
}
// ServerConfig holds the callbacks.
type ServerConfig struct {
PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
VerifiedPublicKeyCallback func(conn ConnMetadata, key PublicKey, permissions *Permissions) (*Permissions, error)
}
func main() {
// Create a server config with both callbacks.
cfg := ServerConfig{
PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
// Store some user‑defined data in ExtraData.
return &Permissions{
CriticalOptions: map[string]string{"no-port-forwarding": ""},
Extensions: map[string]string{"permit-pty": ""},
ExtraData: fmt.Sprintf("user=%s key=%s", conn.User, key.Key),
}, nil
},
VerifiedPublicKeyCallback: func(conn ConnMetadata, key PublicKey, perms *Permissions) (*Permissions, error) {
// Read the data that was stored earlier and add a new field.
if data, ok := perms.ExtraData.(string); ok {
perms.ExtraData = fmt.Sprintf("%s | verified=true", data)
}
return perms, nil
},
}
// Simulate a connection and a public key.
conn := ConnMetadata{User: "alice"}
key := PublicKey{Key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCy..."}
// Step 1: PublicKeyCallback is called.
perms, err := cfg.PublicKeyCallback(conn, key)
if err != nil {
fmt.Println("PublicKeyCallback error:", err)
return
}
fmt.Println("After PublicKeyCallback:", perms)
// Step 2: VerifiedPublicKeyCallback is called with the same key and permissions.
perms, err = cfg.VerifiedPublicKeyCallback(conn, key, perms)
if err != nil {
fmt.Println("VerifiedPublicKeyCallback error:", err)
return
}
fmt.Println("After VerifiedPublicKeyCallback:", perms)
}
What it printed when we ran it on Go 1.27.1
After PublicKeyCallback: &{map[no-port-forwarding:] map[permit-pty:] user=alice key=ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCy...}
After VerifiedPublicKeyCallback: &{map[no-port-forwarding:] map[permit-pty:] user=alice key=ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCy... | verified=true}
Run sends this program (for Solidity, the contract and its tests) to our own sandbox, where it is compiled and run once, with no network, and what it printed or the test report comes back here. Nothing is kept. Runs are counted per visitor for the day so everyone gets a turn; the details are on the legal page.
The 60-second version
This week the Go team added several new features to the standard library. First, the SSH package now lets servers run a callback after a client proves control over a key, and the permissions object can carry arbitrary data. Second, the type checker received two new hasher types that make it easier to hash and compare types consistently, with or without struct tags. Third, XML marshaling gained an “omitzero” tag that omits fields whose values are zero, mirroring the JSON behavior. The releases of Go 1.23.11 and 1.24.5 bring security and bug fixes to the toolchain. Finally, a blog post reminded us that adding type parameters to interfaces opens up surprisingly powerful patterns. These changes expand the expressiveness of Go’s core packages while keeping the language stable and secure.
Written by gpt-oss-20b · claims checked against the sources · archive, not individually reviewed