go install - Installing Binaries and Versioned Tools
Learn how go install compiles Go source code and places the resulting executable into a central location, how to configure the installation target, and how to install versioned tools from remote modules.
The go install command compiles a Go package and moves the resulting binary to a directory your system can find, so you can run it from anywhere. This is the final step after go build – it takes your working program and makes it a first-class tool on your machine.
What go install Does
go install compiles the package in the current directory (or the package path you specify), caches the result, and copies the output binary into the install directory. By default, this directory is $GOPATH/bin if GOBIN is not set, or $GOBIN if it is set explicitly.
Unlike go build, which leaves the binary in your working directory, go install puts the executable where your operating system’s PATH can reach it. After a successful install, you can open any terminal and type the program’s name – no ./ prefix, no remembering where you left the file.
Only for main packages:
go install builds and installs only packages that declare package main and contain a main() function. Library packages without an entry point are compiled to the build cache but produce no executable.
go install vs go build
The two commands share the same compiler and cache, but they differ in what they do with the result.
| Command | Compiles? | Caches work? | Places binary in... | Run from anywhere? |
|---|---|---|---|---|
go build | Yes | Yes | Current directory | No |
go install | Yes | Yes | $GOBIN or $GOPATH/bin | Yes (if PATH is set) |
If you’re actively editing code and testing, go run or go build are faster to cycle through because you don’t need to worry about the global install path. Once the program is stable enough to keep on your machine, go install makes it available globally.
Finding and Setting the Install Path
The go tool decides where to place binaries using the GOBIN environment variable. If GOBIN is empty, it falls back to $GOPATH/bin. In module mode, the GOPATH default is $HOME/go (or %USERPROFILE%\go on Windows), so installed binaries usually land there.
Checking your current GOBIN
Run go env GOBIN to see the explicit value. If the output is blank, go will use the GOPATH/bin fallback.
go env GOBIN
You can also see the exact target path for a package with go list:
go list -f '{{.Target}}'
That prints the full path where go install would place the executable for the package in the current directory.
Empty GOBIN and missing GOPATH:
If both GOBIN and GOPATH are unset or unreachable, go install will fail with a "go install: no install location" error. Always ensure at least one of them points to a writable directory.
Configuring a custom install directory
If you want binaries to land somewhere specific – like a ~/bin folder that’s already in your PATH – set GOBIN persistently with go env -w:
go env -w GOBIN=$HOME/bin
On Windows (PowerShell or Command Prompt) the syntax adapts to your shell’s variable expansion style.
This writes the value to your Go environment configuration file, so all future go install commands will use that directory.
Adding the install directory to your system PATH
The final step is telling your operating system where to find the installed binaries. This is a system configuration, not a Go command.
Add the directory to your PATH by appending a line to your shell profile (.bashrc, .zshrc, etc.):
export PATH=$PATH:$(go env GOBIN 2>/dev/null || echo $HOME/go/bin)
After saving, restart your terminal or run source ~/.bashrc (or the equivalent for your shell).
Verify the setup:
Run go install on a small test program and then type the binary’s name from a different terminal. If it runs without specifying a path, everything is configured correctly.
Installing Your Own Program
To install the package in the current directory, use go install with no arguments. This works as long as the directory is a main package inside a module with a go.mod file.
cd myproject
go install
The binary appears in your GOBIN directory under the module’s base name (the last element of the module path). For example, a module github.com/you/myproject produces a binary called myproject.
You can also install a specific package by its import path:
go install github.com/you/myproject/cmd/server
This builds the main package at cmd/server and installs the binary, using the import path’s last element as the executable name (server).
go install without a go.mod:
If you run go install outside of a module (no go.mod file) and without specifying a version, the tool will complain: "go install: no install location." To install a remote tool without a local module, use the @version suffix described in the next section.
Installing Remote Tools with @version
Beginning with Go 1.16, you can install a command directly from a remote module by appending an @version to the package path. This eliminates the need to first clone a repository or create a local module.
go install golang.org/x/tools/cmd/gopls@latest
@latest fetches the newest tagged release. You can also pin a specific version:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2
The go tool downloads the module at that version, compiles the main package, and places the binary in GOBIN – exactly as if you’d built it locally. Cached build artifacts speed up subsequent installations of the same version.
This @version mechanism is the modern, preferred way to install standalone developer tools like linters, language servers, and code generators. It does not modify your local go.mod, and it works in any directory.
How go install @version works under the hood
When you run go install example.com/cmd/tool@v1.2.3, the toolchain:
- Resolves the module path and version, downloading the source if it isn’t cached.
- Places the module’s dependencies (at that version) into the module cache.
- Compiles the main package and all its dependencies.
- Copies the resulting binary to
GOBIN, naming it after the command’s directory (here,tool).
Because the binary is identified only by its final name – not by the full module path – installing cmd/foo from two different modules overwrites the same foo binary. If you need both, install them into different GOBIN directories or rename them manually.
Cross-Compiling with go install
The Go toolchain can produce binaries for operating systems and architectures different from your current machine. Set the GOOS and GOARCH environment variables before running go install, and the output executable will be built for that target.
GOOS=linux GOARCH=arm64 go install .
That command compiles your program for 64-bit ARM Linux, even if you’re working on a macOS workstation. The binary is placed in $GOBIN/linux_arm64/ (or a subdirectory indicating the target platform), so multiple cross-compiled versions don’t overwrite each other.
Cross-compiled binaries won’t run on your host:
Installing for a foreign platform does not change your local PATH. The resulting binary cannot be executed on your current machine without an emulator. The workflow is used for deploying to remote servers, embedded devices, or CI pipelines.
Cross-compilation also works with the @version syntax:
GOOS=windows GOARCH=amd64 go install example.com/cmd/myapp@v1.0.0
This makes go install a single-step tool for distributing prebuilt binaries across environments, provided you have the necessary C library dependencies handled (see CGO section below).
CGO and go install
When a Go package imports "C" and uses C code, go install invokes the C compiler (by default GCC or Clang) to build those C sources. The binary it produces may be dynamically linked to system C libraries, which can affect portability.
On your own machine, this works transparently if a C compiler is installed. But when cross-compiling or when using CGO, be aware that:
- The installed binary may not run on another machine that lacks the same C library versions.
- For fully static, portable binaries, disable CGO with
CGO_ENABLED=0.
CGO_ENABLED=0 go install .
This forces a pure Go build (no C code) and links statically. If your program depends on C libraries (e.g., SQLite via a C binding), disabling CGO will cause a compilation failure.
CGO and cross-compilation:
Cross-compiling with CGO enabled requires a cross-compilation C toolchain for the target platform, which is significantly more complex. For most deployment use cases, set CGO_ENABLED=0 unless you explicitly need C interop.
Common Mistakes and Troubleshooting
A few errors show up repeatedly when first using go install. Recognizing them speeds up your workflow.
"go install: no install location"
You ran go install outside a module and without a version suffix. Either navigate to a directory with a go.mod file, or use the @version form to install a remote tool.
Binaries not found after installation
The most frequent cause is forgetting to add GOBIN (or $GOPATH/bin) to your PATH. After adding it to your shell profile, you need to restart the terminal or source the profile file. Without this, go install succeeds silently but the executable remains unreachable.
Installing a package that isn't a command
Running go install on a library package (no main function) produces no binary. The go tool will compile and cache it, but won’t place anything in GOBIN. If you expected a tool to appear, check that the package path points to a main package – often under a cmd/ directory.
Overwriting previously installed tools
Because go install places binaries by their directory name, installing github.com/projectA/cmd/tool@latest and then github.com/projectB/cmd/tool@latest overwrites the same tool executable. Use different GOBIN directories or rename the final binary after installation if you need both.
Version conflicts with go.mod
When you run go install inside a module (without @version), it uses the module’s existing go.mod and go.sum. If a tool needs a newer version of a dependency, you might see a compilation error. The @version syntax avoids this by using a separate, isolated build that doesn’t touch your local module.
Best Practices
- Use
go install @latestfor development tools – linters, formatters, code generators. This keeps them isolated from your project’s dependencies and ensures they are up to date. - Set a dedicated
GOBINif you want strict separation between your own binaries and installed tools. For instance,$HOME/binfor personal programs and$HOME/go/binfor external tools. - Prefer
CGO_ENABLED=0for distributable binaries unless you knowingly depend on C code. It produces static executables that run on any same-architecture Linux system. - Clean up old versions –
go installdoes not remove previously installed binaries. If you pin a specific tool version, the old binary remains until you manually delete it. - Use
go list -f '{{.Target}}'before installing to verify where the binary will land, especially when you are inside a module with a non-standard directory structure.
Summary
go install bridges the gap between a compiled Go program and a globally accessible command-line tool. It shares the build logic with go build but adds the final step of placing the binary into a standardized location and keeping it up to date via the build cache. By understanding GOBIN, the @version syntax, and cross-compilation flags, you can use it not only for your own projects but also to populate your development environment with external tooling without polluting your project’s dependency graph.