Fundamentals 8 min read

How Go 1.26’s new Built‑in ‘new’ Accepts Any Expression – Simplify Code and Boost Performance

The article explains the background and need for helper functions that return pointers to values in Go, introduces the upcoming Go 1.26 extension that lets the built‑in new function accept arbitrary expressions, shows practical code examples, demonstrates memory‑leak avoidance and performance gains, and concludes with a brief outlook on the feature’s release.

Go Development Architecture Practice
Go Development Architecture Practice
Go Development Architecture Practice
How Go 1.26’s new Built‑in ‘new’ Accepts Any Expression – Simplify Code and Boost Performance

Go 1.26 is adding a new capability to the built‑in new function: it will accept an arbitrary expression, copy the result into a temporary variable of the same type, and return a pointer to that variable.

Why a helper function was needed

In many large Go projects (e.g., Kubernetes) developers frequently need a pointer to a value for JSON, gRPC, or YAML handling. Since Go forbids taking the address of a literal or constant, a common pattern is to write a small helper that copies the value and returns its address:

func getPointerValue[T any](v T) *T {
    return &v
}

Using this helper, a struct field can be set as d.Num = getPointerValue(12345) instead of the illegal d.Num = &12345.

Memory‑leak concerns

If a pointer to a field of a large struct or an element of a large slice is stored, the entire object stays alive because the garbage collector sees a live reference. For example, assigning d1.Num = &bigObj.Num or d2.Num = &bigSlice[1000] prevents bigObj and bigSlice from being freed, effectively causing a memory leak.

The helper function solves this by copying the value first, so the pointer points to a small temporary variable rather than the large object.

The new new extension

Go 1.26 extends new so that it can take any expression. The compiler rewrites the call by creating a temporary variable, copying the expression result into it, and returning its address. This eliminates the extra function call and gives the compiler more information for escape analysis.

Examples:

// Simple literal
p := new(1234) // *int, value 1234

// Using a function result
func getString() string { return "apocelipes" }
s := new(getString()) // *string, value "apocelipes"

// Combining expressions
s := "Hello, "
p := new(s + getString() + "!") // *string, value "Hello, apocelipes!"

Performance comparison

Benchmarks show that the helper incurs an extra heap allocation and is slower because the compiler treats the helper conservatively during escape analysis. The built‑in new call, however, is specially handled: the temporary variable can be allocated on the stack, avoiding the heap allocation and improving speed.

func BenchmarkOld(b *testing.B) {
    for b.N > 0 {
        p := getPointerValue(123)
        if p == nil || *p != 123 {
            b.Fatal()
        }
    }
}

func BenchmarkNew(b *testing.B) {
    for b.N > 0 {
        p := new(123)
        if p == nil || *p != 123 {
            b.Fatal()
        }
    }
}

Conclusion

Starting with Go 1.26, new can accept any expression, allowing developers to drop custom pointer‑helper functions, write clearer code, and benefit from better performance thanks to the compiler’s special handling of the built‑in.

PerformanceGoGenericsMemorybuiltinnew
Go Development Architecture Practice
Written by

Go Development Architecture Practice

Daily sharing of Golang-related technical articles, practical resources, language news, tutorials, real-world projects, and more. Looking forward to growing together. Let's go!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.