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.

  • 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"
}
# 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.