Using "go get" to download binaries without adding them to go.mod
Hopefully in Go 1.14 there will be a new flag for go get
that does exactly what you are asking. This is tracked in issue #30515 "cmd/go: offer a consistent global install command".
Prior to that, you have a few different options.
Go 1.12 and 1.13: change directory
If you are using Go 1.12 or later, the simplest solution is probably to move outside your current module to a directory without a go.mod
prior to doing the go get
, such as:
$ cd /tmp
$ go get github.com/foo/[email protected]
$ cd - # return to prior directory
Go 1.11, 1.12, 1.13+: gobin
gobin is a module-aware command to install or run binaries that provides additional flexibility, including the ability to install without altering your current module's go.mod
. See the gobin
README and FAQ for more details.
Go 1.11: temporary module
If you are using Go 1.11 with modules, the first step is probably to upgrade to Go 1.12 or 1.13 given there are many improvements in modules. If you are required to use Go 1.11 and want to use the @version
syntax without updating your current module's go.mod
, then one approach is to create a temporary module:
cd $(mktemp -d) && go mod init tempmod && go get github.com/foo/[email protected]
This is because in Go 1.11, you can't use the @version
syntax unless you are in a module, which was relaxed in Go 1.12. This approach has been automated by a simple shell script by @rogpeppe.
Additional Details
In general, the go
command in module-module always determines what module it is "in", which is based on the current working directory when you invoke the go
command. (You could make an analogy to how make
without any args will look for a makefile in the current working directory, or how historically go build
without any args will build the current working directory, etc.).
With modules, go get
looks for a go.mod
file in the current working directory or any of its parents, and go get
will use the constraints listed in any go.mod
as part of solving for versions, as well as update the go.mod
if needed based on doing the go get
. That is why your go.mod
file is updated if you run go get
from within an existing module.
On the other hand, starting with Go 1.12, if you are in a directory that is not part of any module (that is, the directory does not have a go.mod
, nor do any of its parents), then there is no go.mod
to update, but the go
command is still able to operate in module mode and use the @version
syntax.
From the Go 1.12 release notes:
When GO111MODULE is set to on, the go command now supports module-aware operations outside of a module directory, provided that those operations do not need to resolve import paths relative to the current directory or explicitly edit the go.mod file. Commands such as go get, go list, and go mod download behave as if in a module with initially-empty requirements. In this mode, go env GOMOD reports the system's null device (/dev/null or NUL).
Go 1.16 onwards
Go 1.16 (released February 2021) includes a change that makes it possible to install a binary without affecting go.mod
.
Issue 40276 tracks the proposal:
cmd/go: 'go install' should install executables in module mode outside a module
This was implemented in CL 254365. As part of this change, you can run e.g.:
go install golang.org/x/tools/cmd/goimports@latest
to install a binary without affecting go.mod
.
To install a specific version, replace @latest
with e.g. @v0.1.5
.