Question
The Go documentation does not clearly explain the difference between go build and go install.
I expected go install to behave like make install: compile a program and place the final executable in a system location such as /usr/local/bin/my_new_toy. Instead, it appears to place binaries in GOROOT/bin.
What does go install actually do? Can I configure Go to install an executable somewhere else, or should I use a Makefile?
Short Answer
You will learn the difference between go build and go install, where Go installs command-line executables, how GOBIN and GOPATH affect the destination, and when directly choosing an output path is more appropriate.
Concept
go build and go install both compile Go code, but they have different goals.
go buildcompiles a package. For a command package (package main), it normally writes an executable to the current directory. You can also choose an output path with-o.go installcompiles a package and installs command executables into Go's binary installation directory.
For a command, the installation directory is determined in this order:
GOBIN, if it is set.$GOPATH/bin, ifGOBINis not set.
On a typical current Go installation, go install does not install your application into GOROOT/bin. GOROOT is where the Go toolchain itself lives. It may contain tools such as go and gofmt, but it is not the normal destination for programs you develop.
For example, if your GOPATH is /home/alex/go, this command:
go install ./cmd/my_new_toy
installs the executable at:
/home/alex/go/bin/my_new_toy
This behavior matters because Go keeps developer-installed tools separate from system-managed executables. You can add the Go binary directory to your PATH and run installed commands from any directory.
Mental Model
Think of go build as preparing a finished item on your workbench. It compiles the program, and the executable is available where you are working.
Think of go install as putting a finished command into your personal tool drawer. The drawer is GOBIN or $GOPATH/bin, a predictable place where command-line tools can be stored and found later through PATH.
GOROOT is different: it is the factory that contains Go itself. Your own tools generally should not be placed there.
Syntax and Examples
Compile a command in the current project:
go build ./cmd/my_new_toy
If ./cmd/my_new_toy is a package main, Go creates an executable named my_new_toy in the current directory by default.
Install the command into Go's binary directory:
go install ./cmd/my_new_toy
Check the configured locations:
go env GOBIN GOPATH GOROOT
If GOBIN is empty, determine the default install directory with:
go env GOPATH
The executable is installed under that path's bin directory.
Use a custom Go install directory
Set GOBIN to an absolute path:
export GOBIN="$HOME/.local/bin"
go install ./cmd/my_new_toy
The binary will be written to:
$HOME/.local/bin/my_new_toy
Make sure the directory is on your PATH:
export PATH="$HOME/.local/bin:$PATH"
Choose an exact output file
When you need a particular destination, use go build -o:
go build -o /usr/local/bin/my_new_toy ./cmd/my_new_toy
Writing to /usr/local/bin commonly requires administrator permission:
sudo go build -o /usr/local/bin/my_new_toy ./cmd/my_new_toy
For deployment, it is often better to build into a temporary or release directory first, then copy the executable using the deployment process.
Step by Step Execution
Consider this project layout:
example.com/toys
└── cmd
└── greet
└── main.go
cmd/greet/main.go:
package main
import "fmt"
func main() {
fmt.Println("Hello!")
}
Run:
go install ./cmd/greet
What happens:
- Go reads the package at
./cmd/greet. - It sees
package main, so this package produces an executable. - Go compiles the package and its dependencies. Previously compiled dependency results may be reused from Go's build cache.
- Go checks
GOBIN. - If
GOBINis set, it writesgreetthere. Otherwise, it writesgreetto$GOPATH/bin. - If that destination directory is on
PATH, you can run the command from anywhere:
greet
On Windows, the installed file is normally named greet.exe.
Real World Use Cases
-
Installing development tools: Install commands such as linters, code generators, or test helpers into
$GOPATH/binorGOBIN.go install golang.org/x/tools/cmd/goimports@latest -
Installing a command from a repository: Build and install a versioned command without first cloning the repository.
go install example.com/tools/acmecli@v1.4.0 -
Building a release artifact: Put a binary in a release directory with a known name.
go build -o dist/my_new_toy ./cmd/my_new_toy -
System-wide deployment: A package manager, container image build, CI job, or administrator copies a tested binary to
/usr/local/binor another controlled location. -
Multiple project commands: A repository can use
cmd/api,cmd/worker, andcmd/adminas separate executable entry points.
Real Codebase Usage
In real Go projects, go install is most commonly used for developer tools, while go build -o is commonly used for application artifacts.
Install a pinned development tool
A tool can be installed at an explicit version:
go install example.com/tools/mockgen@v1.6.0
Using an explicit version makes automation more repeatable than always using @latest.
Build an application for CI or releases
A CI pipeline usually creates an artifact in a project directory:
go build -trimpath -o dist/server ./cmd/server
The pipeline can then test, archive, sign, copy, or package dist/server.
Use a task runner only when repeated commands need coordination
You do not need a Makefile merely to install one Go command. A Makefile can still be useful when a project needs multiple repeatable actions, such as formatting, testing, generating code, building several binaries, and preparing a release.
build:
go build -o dist/my_new_toy ./cmd/my_new_toy
test:
go test ./...
The Makefile is optional; it is a convenience layer around commands, not a requirement of Go.
Common Mistakes
Assuming go install uses /usr/local/bin
This is not Go's default behavior. go install uses GOBIN, or $GOPATH/bin when GOBIN is unset.
Avoid the assumption by checking:
go env GOBIN GOPATH
Confusing GOROOT with GOPATH
GOROOTis the Go installation and toolchain location.GOPATHis a workspace-related location that, among other things, provides the defaultbindirectory for installed commands.
Do not manually copy your programs into GOROOT/bin; a Go upgrade may replace that directory.
Forgetting to add the install directory to PATH
The command can be installed successfully but still appear to be “not found.”
export PATH="$(go env GOPATH)/bin:$PATH"
If you use GOBIN, add GOBIN instead.
Setting GOBIN to a relative path
This is invalid:
export GOBIN=bin
Use an absolute path:
export GOBIN="$HOME/.local/bin"
Using go build when you intended a reusable installed tool
This command creates an executable in the working directory by default:
go build ./cmd/greet
Use go install ./cmd/greet when you want the command placed in your configured Go binary directory.
Installing directly into a privileged directory during ordinary development
Avoid making normal builds depend on sudo. Build to a local directory first, then use a controlled installation or packaging step when needed.
Comparisons
| Command or location | Main purpose | Typical output location | Best use |
|---|---|---|---|
go build ./cmd/app | Compile a command | Current directory by default | Quick local builds |
go build -o dist/app ./cmd/app | Compile to an exact path | Path passed to -o | CI, releases, deployment artifacts |
go install ./cmd/app | Compile and install a local command | GOBIN or $GOPATH/bin | Commands you want on your PATH |
go install module/path@version | Install a versioned external command | GOBIN or $GOPATH/bin | Developer tools and CLIs |
go run ./cmd/app | Compile and run without keeping a named executable | Temporary build output | Trying a program quickly |
go build is about producing a build result. go install is about placing a command in Go's configured command directory. go run is about immediately executing code.
Cheat Sheet
# Show Go directories
go env GOROOT GOPATH GOBIN
# Build a command; output is normally in the current directory
go build ./cmd/app
# Build to a specific file
go build -o dist/app ./cmd/app
# Install a local command to GOBIN or GOPATH/bin
go install ./cmd/app
# Install a versioned command from a module
go install example.com/tool/cmd/tool@v1.2.3
# Configure a custom installation directory (must be absolute)
export GOBIN="$HOME/.local/bin"
go install ./cmd/app
# Make installed commands discoverable
export PATH="$HOME/.local/bin:$PATH"
Rules to remember:
GOBINtakes priority over$GOPATH/bin.- If
GOBINis empty, commands go to$GOPATH/bin. GOROOTis for the Go toolchain, not normally for your applications.- Use
go build -owhen an application must be written to an exact destination.
FAQ
What is the difference between go build and go install?
go build compiles code and produces an executable in the current directory by default for command packages. go install compiles and places command executables in GOBIN or $GOPATH/bin.
Where does go install put binaries?
It uses GOBIN if that environment variable is set. Otherwise, it uses $GOPATH/bin.
Does go install install programs into GOROOT/bin?
Normally, no. GOROOT/bin belongs to the Go toolchain. Check your actual configuration with go env GOROOT GOPATH GOBIN.
How do I change the go install destination?
Set GOBIN to an absolute directory, such as export GOBIN="$HOME/.local/bin".
Can I make Go install directly to /usr/local/bin?
You can set GOBIN=/usr/local/bin if you have permission, but this is often not ideal for ordinary development. Alternatively, use go build -o /usr/local/bin/app, usually through a controlled deployment step.
Do I need a Makefile to install a Go program?
No. go install and go build -o cover common cases. Use a Makefile or another task runner only when you want convenient, repeatable project commands.
Why is an installed Go command not found in my shell?
Its destination directory is probably not on your PATH. Add GOBIN or $GOPATH/bin to PATH.
Should I use @latest with go install?
@latest is convenient for interactive use. For reproducible scripts and team tooling, prefer a specific version such as @v1.2.3.
Mini Project
Description
Create a small Go command-line program and practice both building a release artifact at a chosen path and installing the command into Go's configured binary directory. This reflects the common distinction between shipping an application and installing a developer tool.
Goal
Build and install a greet command, then verify where each command places its executable.
Requirements
Create a Go command named greet that prints a greeting.
Keep learning
Related questions
Are Go Maps Passed by Value or Reference?
Learn Go map parameter and return semantics: maps are passed by value, while copies share underlying data. Know when map pointers are useful.
Authentication for Go REST APIs: Sessions, Tokens, and Middleware
Learn practical authentication patterns for Go REST APIs, including password hashing, server sessions, bearer tokens, middleware, and security rules.
Automatic Build Versioning in Go: Embed Incrementing Build Numbers
Learn how to add automatic build versioning in Go using linker flags, build metadata, CI counters, and Git-based version values.