Kinoko's TIL Log

Go Modern Syntax Fixes

The Point

Go 1.22+ introduced several language-level changes. go fix can automatically upgrade old patterns to modern ones: loop variable capture, interface{} to any, and inline pointer helper functions can all be removed or simplified.

Explanation

1. Remove unnecessary loop variable captures

Before Go 1.22, the for loop variable was shared across all iterations at the same memory address. Closures captured the same variable, causing a classic bug:

 1// Before Go 1.22: all goroutines print the same value (the last one)
 2for _, v := range items {
 3    go func() { fmt.Println(v) }()
 4}
 5
 6// Old workaround: redeclare inside the loop to force a new variable
 7for _, v := range items {
 8    v := v  // capture a new variable per iteration
 9    go func() { fmt.Println(v) }()
10}

Starting from Go 1.22, each iteration has an independent variable, making v := v redundant. go fix removes it automatically.

2. Replace interface{} with any

Go 1.18 introduced any as a type alias for interface{}. They are identical, but any is shorter:

1// Old
2func process(v interface{}) {}
3var m map[string]interface{}
4
5// New
6func process(v any) {}
7var m map[string]any

3. Remove inline pointer helper functions

Taking a pointer to a literal used to require a helper function (because Go does not allow &"hello" directly):

1// Old workaround
2func strPtr(s string) *string { return &s }
3func intPtr(i int) *int { return &i }
4
5name := strPtr("Alice")
6age  := intPtr(30)

Modern Go can replace all type-specific helpers with a single generic version, or just declare a variable and take its address:

1// One generic helper replaces all
2func ptr[T any](v T) *T { return &v }
3
4// Or just declare and reference
5name := "Alice"
6req.Name = &name

What is a literal?

A literal is a fixed value written directly in code – not a variable, not a computed result, just the value as written:

1"hello"        // string literal
242             // integer literal
3true           // boolean literal
4[]int{1, 2, 3} // slice literal

Go does not allow taking a pointer to a literal (&"hello" is a compile error) because literals have no memory address. You must assign to a variable first – that is why pointer helper functions existed.

For details on generics, see the Go Generics post.

Knowledge Sugar

What is go fix?

go fix is an official Go refactoring tool that applies mechanical fixes for each version’s breaking changes or language updates. Running it once when upgrading saves a lot of manual edits.

1go fix ./...

Why is the Go 1.22 loop variable change important?

This bug existed for over ten years and was one of Go’s most famous gotchas – nearly every Go developer hit it at least once. Go 1.22 changed the behavior to match intuition, which is a significant language-level fix.

#go #til

← Back to Main Page