Modernizing Your Go Code with the New go fix Command

By

The Go 1.26 release brought a fully rewritten go fix subcommand that helps developers keep their codebases up to date with the latest language and library features. This Q&A covers everything you need to know to start using go fix effectively, from running it to understanding the available fixers and best practices.

What is the go fix command and what does it do?

go fix is a tool that automatically updates your Go source files to take advantage of modern language and library features. It uses a collection of analysis algorithms (called fixers) to identify opportunities for improvement, such as replacing interface{} with any, using strings.Cut instead of manual splitting, or removing redundant loop variable redeclarations. The command is designed to be run each time you update your Go toolchain to a newer release, ensuring your code stays current.

Modernizing Your Go Code with the New go fix Command
Source: blog.golang.org

How do you run go fix on your project?

Like go build and go vet, go fix accepts package patterns. To fix all packages in the current directory and its subdirectories, run:

$ go fix ./...

On success, the command silently updates your source files in place. It skips generated files, because fixing those should be done by updating the generator itself. A recommended practice is to start from a clean git state before running go fix, so that the resulting changes are clearly attributable to the tool, making code reviews smoother.

How can you preview changes before applying them?

Use the -diff flag to see what changes go fix would make without actually modifying your files:

$ go fix -diff ./...

This displays a unified diff output. For example, it might show replacing a manual strings.IndexByte and slicing with strings.Cut. This is especially useful for understanding the impact of a fixer before committing to applying it across a large codebase.

What fixers are available in go fix?

You can list all registered fixers with:

$ go tool fix help

The output includes names and short descriptions. Some examples:

  • any – replaces interface{} with any
  • buildtag – checks and updates //go:build directives
  • fmtappendf – replaces []byte(fmt.Sprintf) with fmt.Appendf
  • forvar – removes redundant redeclaration of loop variables
  • hostport – checks address formats for net.Dial
  • inline – applies fixes based on //go:fix inline comments
  • mapsloop – replaces manual map loops with maps package calls
  • minmax – converts if/else to min or max calls

How does the forvar fixer modernize loop variable handling?

The forvar fixer addresses a common idiom from before Go 1.22, where developers would manually redeclare loop variables inside loops to avoid capturing the same variable by reference. For example, before Go 1.22 it was typical to write:

Modernizing Your Go Code with the New go fix Command
Source: blog.golang.org
for _, v := range slice {
    v := v // redeclare to avoid capture issues
    // use v
}

Since Go 1.22, loop variables have per-iteration semantics, making such redeclarations unnecessary. The forvar fixer automatically removes these redundant lines, cleaning up your code and making it more idiomatic.

When should you run go fix, and are there any precautions?

It is recommended to run go fix ./... on your project each time you upgrade to a newer Go toolchain release. This ensures your code consistently uses the latest language and library features. Before running, always commit or stash your current work so that you can review the changes cleanly. The command respects generated files (identified by a // Code generated comment) and omits them, since the proper fix for those is to update the code generator itself. After running, review the diffs—especially if you used -diff—and commit the changes with a clear message.

Related Articles

Recommended

Discover More

Brooks's Law Proven Timeless: Why Adding Staff to Late Projects Still FailsUnderstanding and Defending Against the Silver Fox Springs Campaign: A Tax-Themed APT AttackReact Native 0.82: A Major Milestone for Mobile DevelopmentKubernetes v1.36 Elevates Pod-Level Resource Scaling to Beta – No Restart Required10 Ways Grafana Assistant Transforms Incident Response with Pre-Built Infrastructure Knowledge