Native per-project tools in Go 1.24
There are some exciting news in the Go community as of recently on how to manage tools in Go projects. With the next release of Go (Go 1.24, expected to be released in February 2025), it seems we'll finally have a way to natively define per-project tools! 🎉
This hopefully means no more Makefile
and/or tools.go
for managing project
tooling. And it looks like e.g. Dependabot will support this out of the box too.
Giving this a spin with gotip
You can try it out today using
gotip
:
Let's have a look at the docs for go tool
(in this case, gotip tool
):
$ gotip help tool
usage: go tool [-n] command [args...]
Tool runs the go tool command identified by the arguments.
Go ships with a number of builtin tools, and additional tools
may be defined in the go.mod of the current module.
With no arguments it prints the list of known tools.
The -n flag causes tool to print the command that would be
executed but not execute it.
For more about each builtin tool command, see 'go doc cmd/<command>'.
Then let's create a project and add some tools to it:
gotip mod init go-playground
gotip get -tool github.com/alta/protopatch/cmd/protoc-gen-go-patch
gotip get -tool gotest.tools/gotestsum
There's a new tool
section in the go.mod
!
$ cat go.mod
module go-playground
go 1.24
tool (
github.com/alta/protopatch/cmd/protoc-gen-go-patch
gotest.tools/gotestsum
)
require (
github.com/alta/protopatch v0.5.3 // indirect
github.com/bitfield/gotestdox v0.2.2 // indirect
github.com/dnephin/pflag v1.0.7 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/fatih/structtag v1.2.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
golang.org/x/mod v0.16.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.19.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gotest.tools/gotestsum v1.12.0 // indirect
)
You can now run tools like this:
And if you step out of the project, the tool you just added is no longer available.
You can also see which bundled tools are available by default with Go 1.24:
$ gotip tool
addr2line
asm
buildid
cgo
compile
covdata
cover
dist
distpack
doc
fix
link
nm
objdump
pack
pprof
preprofile
test2json
trace
vet
Summary
I think this development is great. It's something my colleagues and myself have been waiting for.
This new go tool
workflow introduces less complexity (than the
Makefile
/tools.go
setup) but it likely won't solve all the use cases, like
splitting out test dependencies from the production dependencies (EDIT: this do
seem possible, see amendment below) or solve/improve integration with
IDEs/editors.
Amendment, 2024-12-04
It seems like it will be possible to split out dependencies from the main
go.mod
file:
Amendment, 2024-12-20
!!! quote "Quoting ConradIrwin from GitHub comment"
- Tool executables live in the build cache, and are built on demand (and expired
when unused). This lets go tool select which version of a tool is used
depending on the active module.
- You invoke them with `go tool <toolname>`. If you want to (and versioning is
not a concern) you can install all tools for the current module to `GOBIN`
with `go install tool`.
- Tool dependencies participate in the same module graph as imported
dependencies, and require/replace/exclude directives apply in the same way.
- If you want to remove a tool dependency, you can use `go get -tool` followed
by `go get -u`.
— Source at [golang/go#48429](https://github.com/golang/go/issues/48429#issuecomment-2547760589)