Representative interview topic

Go Coding Interview: Evaluating Go 1.26 new(expr) and go fix

CodingMedium
Offer.cc Editorial TeamPublished Updated

Question

A team is upgrading to Go 1.26. Explain new(expr), recursive generic constraints, and the new go fix, then design a safe migration and rollback process.

Prompt and context

A Go service is moving to 1.26 to reduce pointer-initialization boilerplate and modernize old APIs. Explain new(expr), self-referential generic constraints, and the rewritten go fix, then design a migration pipeline that does not push behavior changes directly to production.

This fits Go backend, infrastructure, and developer-tool roles. The Go 1.26 release notes define value expressions for new, recursive generic constraints, and go/analysis-based modernizers; the Go Blog adds API migration and //go:fix inline details. This article is based on public sources, not a claim about a company’s interview bank.

What the interviewer evaluates

The interviewer is checking whether you distinguish syntax convenience, type-system expressiveness, and automated-rewrite risk. A strong answer explains that new(expr) points to a new initialized variable, generic constraints still require a method set, and go fix applies only under an appropriate module version, with diff review, tests, and staged rollout.

Clarifying questions

  • What is the service’s minimum Go version and module go directive?
  • Does a pointer field mean “missing,” or is a zero value also meaningful?
  • May an automatic modernizer change APIs across packages?
  • Must the migration preserve binary compatibility, serialization compatibility, or only test behavior?

A 30-second answer

“In Go 1.26, new(expr) creates an initialized pointer, useful for optional JSON or protobuf fields, but it does not change nil versus zero-value semantics. Generic constraints may refer to the generic type itself, which expresses recursive interfaces. The rewritten go fix provides auditable modernizers. I would pin the module version, generate a reviewable diff, run tests, static checks, and serialization compatibility tests, then canary the change. A regression rolls back the patch or disables one fixer.”

Step-by-step solution

The key property of new(expr) is value initialization: p := new(300) creates a new variable whose value is 300; it does not return the address of an existing variable in the expression. This is useful in struct literals and function arguments that need a pointer, such as an optional *int. The protocol must still distinguish nil, a pointer to zero, and an omitted field.

Go 1.26 allows a generic type to appear in its own type-parameter constraint. Adder[A Adder[A]] can require A to provide Add(A) A. This expands constraint expressiveness but does not guarantee runtime recursion termination; algorithms still handle empty structures, depth, and concrete method implementations. Confirm the compiler and dependency module versions before migrating.

The new go fix uses the same go/analysis framework as go vet, ships modernizers, and supports source-level API migrations declared with //go:fix inline. Its goal is behavior preservation, but teams should treat each patch as review input: scope the directories, pin the toolchain, preserve the diff, and reject unrelated formatting.

Version gates decide whether a fixer runs. The official guidance requires the module’s go.mod or build constraint to meet the appropriate version, preventing an old module from adopting new syntax early. Run go fix on an isolated branch, then run gofmt, go vet, unit and integration tests, and benchmarks. Add golden comparisons for JSON, protobuf, reflection, and unsafe-heavy code.

Canary by package or service and observe binaries, error rate, serialized bytes, latency, and memory. If one modernizer changes behavior, revert that fixer’s patch rather than the entire toolchain. If the compiler or runtime upgrade itself is at fault, roll back the build image and module version. Record the Go version, fixer name, diff, and test evidence.

Model answer

I would use four stages: semantic confirmation, automated rewrite, verification, and canary. First confirm that new(expr) changes only pointer initialization and preserves nil, zero-value, and serialization contracts; confirm recursive generics only expand constraints. Run go fix with a pinned module version and keep an auditable diff. Every patch passes gofmt, go vet, tests, benchmarks, and serialization goldens before service-level rollout with a per-fixer rollback path.

Common mistakes

  • Mistake → treat new(0) as a nil pointer; Why it fails → it points to a new variable containing zero; Fix → keep nil for absence and test serialization.
  • Mistake → commit new syntax under an old go.mod; Why it fails → the old toolchain cannot parse it and the fixer should not run; Fix → update the version gate and pin CI.
  • Mistake → run go fix across the repository without review; Why it fails → cross-package API and unrelated edits can slip in; Fix → scope directories, review diffs, and canary each fixer.
  • Mistake → run only unit tests; Why it fails → JSON/protobuf and performance regressions may escape; Fix → add golden, integration, and benchmark checks.

Follow-up questions

How does new(expr) differ from &expr?

Both produce a pointer, but new(expr) allocates and initializes a new variable from a value expression. &expr requires an addressable expression and takes the address of an existing variable. Migration reviews should check lifetime, addressability, and accidental sharing.

How do you show that go fix preserved behavior?

Keep one diff per fixer, run compilation, static analysis, unit and integration tests, and compare serialized output, error codes, and key benchmarks with goldens or statistical thresholds. Reflection and unsafe-heavy code also receive manual review and a small canary.

What risks come with recursive generic constraints?

They express recursive interfaces but can make constraints and compiler errors harder to understand, and they do not guarantee algorithm termination. Bound constraint complexity, add compile-fail tests for missing methods, and provide clear public type aliases and examples.

Public sources

Related questions

Related interview tool

Use Screenshot for a coding prompt

Capture the problem, then work through the constraints, solution, code, edge cases, and complexity in order.

View the tool