Go

What does the Go 1.24 tool directive replace, and how do you use it?

Question 421MediumGo 1.22 to 1.25

Before 1.24 the convention was a tools.go file with //go:build tools and blank imports, used to pin versions of developer tools (stringer, mockgen, sqlc) in go.mod. Go 1.24 made this a first-class feature: a tool directive in go.mod, run with go tool.

go get -tool golang.org/x/tools/cmd/stringer@v0.28.0
# go.mod gains:
tool golang.org/x/tools/cmd/stringer

go tool stringer -type=Color     # builds (cached) and runs the pinned version
go get tool                      # upgrade all tools
go install tool                  # install all tools into GOBIN

//go:generate go tool stringer -type=Color

Benefits: tool versions go through MVS and go.sum like any other dependency, every developer and CI job runs the same version, there is no go install step and no $PATH drift, and executables are cached in the build cache.

Gotchas: tool dependencies join your module graph and can raise versions of shared libraries, since MVS applies to them too. If that becomes a problem, put tools in a separate module (go tool -modfile=tools/go.mod). Remove a tool with go get -tool pkg@none.

More on Modules, Packages & Tooling

All 36 Modules, Packages & Tooling questions