Installing Go
macOS
brew install go # Homebrew
# or download a .pkg installer from https://go.dev/dl/
Linux
# Recommended: download the official tarball, do NOT use the distro package
wget https://go.dev/dl/go1.22.0.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.22.0.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
Windows
Use the MSI installer from https://go.dev/dl/, or winget install GoLang.Go.
Verify
go version
# go version go1.22.0 darwin/arm64
Important environment variables
| Variable | What it is |
|---|---|
GOROOT |
Where Go itself is installed. Usually set automatically. |
GOPATH |
Workspace for go install binaries ($GOPATH/bin) and module cache. |
GOMODCACHE |
Where downloaded module sources live ($GOPATH/pkg/mod by default). |
GOOS/GOARCH |
Target OS / architecture for cross-compilation. |
GO111MODULE |
Legacy switch. Modules are always on in modern Go; ignore unless needed. |
GOPROXY |
Module proxy. Default https://proxy.golang.org,direct. |
GOPRIVATE |
Glob of module paths that should bypass the proxy (for private code). |
Inspect any of them with:
go env GOPATH
go env GOROOT
go env # all of them
Set one persistently:
go env -w GOPRIVATE=github.com/mycompany/*
The most-used commands
| Command | What it does |
|---|---|
go mod init |
Create a new module (go.mod) in the current directory. |
go mod tidy |
Add missing / remove unused dependencies; also writes go.sum. |
go build |
Compile the current package(s); produces an executable for main. |
go run |
Compile and run in one step (useful for quick iteration). |
go install |
Build and place the binary in $GOPATH/bin. |
go test |
Run tests in the current package(s). |
go fmt |
Format the source. Always run before committing. (gofmt directly) |
go vet |
Static analysis: shadowed vars, printf mistakes, suspicious code. |
go doc |
Print documentation for a package or symbol from the terminal. |
go work |
Multi-module workspaces (Go 1.18+). |
go generate |
Run //go:generate directives. Used for codegen. |
The ./... syntax means "this directory and every subdirectory". So
go test ./... runs every test in the module.
Recommended editor setup
- VS Code with the official "Go" extension. It uses
gopls, the Go language server, for completion, jump-to-definition, refactors and on-save formatting. - GoLand (JetBrains) — paid, but excellent.
- Neovim / Helix — also use
gopls; configure your LSP client.
A typical settings.json snippet for VS Code:
{
"editor.formatOnSave": true,
"[go]": {
"editor.defaultFormatter": "golang.go",
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
},
"go.useLanguageServer": true,
"go.lintTool": "golangci-lint",
"go.lintOnSave": "package"
}
Optional but recommended tools
# linter aggregator (vet + many more)
brew install golangci-lint # mac
# or: see https://golangci-lint.run/usage/install/
# auto-import + formatter, superset of gofmt
go install golang.org/x/tools/cmd/goimports@latest
# data-race detector — built into the toolchain, just add -race
go test -race ./...
# coverage
go test -cover ./...
go test -coverprofile=cover.out ./...
go tool cover -html=cover.out
Hello, world
Create a file hello.go:
package main
import "fmt"
func main() {
fmt.Println("hello, world")
}
Run it:
go mod init hello # only the first time
go run .
You should see hello, world. If you do, your environment is ready and you
can move on to Chapter 3.