# Go — User Guide

## 1. Quick Start

Go is an open-source, statically typed, compiled programming language designed at Google for building reliable, efficient software at scale. It compiles directly to machine code, features built-in concurrency primitives (goroutines and channels), and produces single, self-contained binaries that run without external dependencies. Go powers much of the modern cloud infrastructure — Docker, Kubernetes, Terraform, and thousands of production services worldwide.

**Key features:**

- **Fast compilation** — large projects compile in seconds, not minutes
- **Garbage collected** — automatic memory management without manual allocation
- **Concurrency via goroutines and channels** — lightweight threads (goroutines cost ~2KB each) with type-safe communication
- **Cross-compilation** — build for any supported OS/architecture from any machine with `GOOS` and `GOARCH`
- **Single binary output** — no runtime dependencies, no DLL hell, deploy by copying one file
- **Comprehensive standard library** — HTTP servers, JSON, crypto, compression, databases, and more built in
- **Module system** — built-in dependency management with `go.mod` and reproducible builds via `go.sum`
- **Built-in testing** — `go test` includes unit tests, benchmarks, fuzz testing, coverage, and race detection

**Prerequisites:** A 64-bit operating system — Linux, macOS, Windows, or FreeBSD on supported architectures.

**Install Go:**

Download the latest release from [go.dev/dl](https://go.dev/dl/) and follow the instructions for your platform, or use your system package manager.

**Hello World in 60 seconds:**

```bash
mkdir hello && cd hello
go mod init example/hello
```

Create `main.go`:

```go
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}
```

Run it:

```bash
go run .
```

```text
Hello, World!
```

> [!TIP]
> `go run .` compiles and executes in one step — perfect for quick iteration. For production, use `go build` to create a reusable binary.

**What's next:**

- [Section 2: Installation](#2-installation) — detailed setup for every platform
- [Section 3: Configuration](#3-configuration) — environment variables and module setup
- [Section 4: Core Usage](#4-core-usage) — every `go` subcommand explained
- [Section 5: Common Tasks](#5-common-tasks) — 25+ recipes for real-world workflows

---

## 2. Installation

### System Requirements

| Platform | Architecture | Minimum OS Version |
|----------|-------------|-------------------|
| Linux | amd64, arm64, 386, armv6l, loong64, mips*, ppc64*, riscv64, s390x | Kernel 2.6.32+ (glibc 2.17+) |
| macOS | amd64, arm64 (Apple Silicon) | macOS 11 Big Sur+ |
| Windows | amd64, arm64, 386 | Windows 10 / Server 2016+ |
| FreeBSD | amd64, arm64, 386, armv6l, riscv64 | FreeBSD 13+ |

### Install Methods

#### Binary Download (Recommended)

Download the appropriate archive from [go.dev/dl](https://go.dev/dl/).

**Linux (amd64):**

```bash
wget https://go.dev/dl/go1.24.2.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.24.2.linux-amd64.tar.gz
```

Add to your shell profile (`~/.bashrc`, `~/.zshrc`, etc.):

```bash
export PATH=$PATH:/usr/local/go/bin
export PATH=$PATH:$(go env GOPATH)/bin
```

**macOS (arm64 / Apple Silicon):**

```bash
wget https://go.dev/dl/go1.24.2.darwin-arm64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.24.2.darwin-arm64.tar.gz
```

Or download the `.pkg` installer from go.dev/dl and double-click to install.

**Windows (amd64):**

Download the `.msi` installer from [go.dev/dl](https://go.dev/dl/) and run it. The installer automatically adds `C:\Go\bin` to your system `PATH`.

Alternatively, download the `.zip` archive and extract to `C:\Go`, then manually add `C:\Go\bin` to your `PATH` environment variable.

> [!IMPORTANT]
> On all platforms, ensure `$GOPATH/bin` (default: `~/go/bin` on Unix, `%USERPROFILE%\go\bin` on Windows) is in your `PATH`. Binaries installed with `go install` are placed there.

#### Linux Package Manager

**Ubuntu/Debian:**

```bash
sudo apt update
sudo apt install golang-go
```

**Fedora:**

```bash
sudo dnf install golang
```

**Arch Linux:**

```bash
sudo pacman -S go
```

> [!WARNING]
> Distribution packages often lag behind the official release. For the latest version, use the binary download method. Check your version with `go version` after installing.

#### macOS Homebrew

```bash
brew install go
```

Homebrew installs Go to `/opt/homebrew/Cellar/go/` (Apple Silicon) or `/usr/local/Cellar/go/` (Intel) and symlinks the binary into your PATH.

#### From Source

Building Go from source requires a working Go installation (Go 1.22.6 or later) as a bootstrap compiler:

```bash
git clone https://go.googlesource.com/go goroot
cd goroot/src
./all.bash
```

```text
ALL TESTS PASSED

---
Installed Go for linux/amd64 in /home/user/goroot
Installed commands in /home/user/goroot/bin
```

The `all.bash` script builds the toolchain, runs all tests, and installs binaries to `../bin/`. Add that directory to your `PATH`.

For faster builds without running all tests, use `./make.bash` instead.

### Post-Install Verification

```bash
go version
```

```text
go version go1.24.2 linux/amd64
```

Verify your environment:

```bash
go env GOROOT GOPATH GOBIN
```

```text
/usr/local/go
/home/user/go

```

An empty `GOBIN` means binaries install to `$GOPATH/bin`.

### GOROOT and GOPATH

- **GOROOT** — where Go itself is installed (`/usr/local/go` on Linux/macOS, `C:\Go` on Windows). You rarely need to set this manually; the `go` command infers it from its own location.
- **GOPATH** — your workspace for downloaded modules and installed binaries. Defaults to `$HOME/go`. The `go` command uses `$GOPATH/pkg/mod` for the module cache and `$GOPATH/bin` for installed binaries.

### Managing Multiple Go Versions

Install additional Go versions side-by-side:

```bash
go install golang.org/dl/go1.23.0@latest
go1.23.0 download
go1.23.0 version
```

```text
go version go1.23.0 linux/amd64
```

Each version installs to `$HOME/sdk/go1.23.0/` and creates a wrapper command named for that version.

---

## 3. Configuration

### The `go env` Command

View all environment variables:

```bash
go env
```

View specific variables:

```bash
go env GOOS GOARCH CGO_ENABLED
```

```text
linux
amd64
1
```

Persistently set a variable (writes to `$GOENV` file, default `~/.config/go/env`):

```bash
go env -w GOPROXY=https://proxy.golang.org,direct
```

Unset a persistent override:

```bash
go env -u GOPROXY
```

Show only variables that differ from defaults:

```bash
go env -changed
```

Output as JSON:

```bash
go env -json
```

### Key Environment Variables

| Variable | Default | Purpose |
|----------|---------|---------|
| `GOPATH` | `$HOME/go` | Workspace root — module cache, installed binaries |
| `GOBIN` | `$GOPATH/bin` | Where `go install` places binaries |
| `GOPROXY` | `https://proxy.golang.org,direct` | Module proxy URL(s), comma-separated; `direct` = fetch from origin |
| `GOPRIVATE` | (empty) | Glob patterns for private modules (skips proxy and checksum DB) |
| `GONOSUMDB` | (empty) | Glob patterns to skip checksum verification |
| `GONOSUMCHECK` | (empty) | Glob patterns to skip checksum lookup in the sum DB |
| `GONOPROXY` | (empty) | Glob patterns to fetch directly (bypass proxy) |
| `GOFLAGS` | (empty) | Default flags applied to all `go` commands |
| `CGO_ENABLED` | `1` (native), `0` (cross) | Enable/disable cgo (C interop) |
| `GOOS` | Host OS | Target operating system for compilation |
| `GOARCH` | Host arch | Target architecture for compilation |
| `GOTMPDIR` | System temp | Directory for temporary build files |
| `GOMODCACHE` | `$GOPATH/pkg/mod` | Module download cache location |
| `GOEXPERIMENT` | (empty) | Comma-separated experimental features to enable |
| `GOTOOLCHAIN` | `auto` | Go toolchain selection policy (`local`, `auto`, `path`, or specific version) |
| `GOTELEMETRY` | `local` | Telemetry mode: `off`, `local`, or `on` |

> [!TIP]
> Set `GOPRIVATE` for your company's module path to prevent private code from being sent to the public proxy and checksum database: `go env -w GOPRIVATE=github.com/mycompany/*`

### Module Configuration: go.mod

Every Go project starts with a `go.mod` file created by `go mod init`:

```bash
go mod init github.com/yourname/myproject
```

This creates a `go.mod` file:

```go
module github.com/yourname/myproject

go 1.24.2

require (
    github.com/gin-gonic/gin v1.9.1
    golang.org/x/sync v0.7.0
)

require (
    // indirect dependencies listed here
    golang.org/x/net v0.25.0 // indirect
)
```

**Directives in go.mod:**

| Directive | Purpose | Example |
|-----------|---------|---------|
| `module` | Declares the module path | `module github.com/user/repo` |
| `go` | Minimum Go version required | `go 1.24.2` |
| `toolchain` | Specific toolchain version | `toolchain go1.24.2` |
| `require` | Declares dependencies | `require golang.org/x/sync v0.7.0` |
| `replace` | Substitutes a module (local dev, forks) | `replace example.com/mod => ../local-mod` |
| `exclude` | Excludes a specific module version | `exclude example.com/mod v1.2.3` |
| `retract` | Marks versions as retracted by module author | `retract v1.0.0` |

**go.sum** — the companion file `go.sum` contains cryptographic checksums of every dependency. It is auto-generated and should be committed to version control. Do not edit it manually.

For the full configuration reference including all build flags, linker options, and advanced compiler directives, see the Admin Guide.

---

## 4. Core Usage

The `go` command is the single entry point for building, testing, managing dependencies, and working with Go code. Every subcommand follows the pattern:

```bash
go <command> [arguments]
```

### 4.1 Building and Running

#### `go build` — Compile Packages

Compile one or more packages into a binary:

```bash
go build .
```

This creates an executable named after the current directory. Specify an output name:

```bash
go build -o myapp .
```

```text
# produces: ./myapp
```

**Common flags:**

| Flag | Purpose |
|------|---------|
| `-o <file>` | Set output file name/path |
| `-v` | Print package names as they compile |
| `-race` | Enable race detector (adds ~2x slowdown, ~5-10x memory) |
| `-tags <list>` | Comma-separated build tags |
| `-ldflags <flags>` | Pass flags to the linker (e.g., `-s -w` to strip debug info) |
| `-gcflags <flags>` | Pass flags to the compiler (e.g., `-N -l` to disable optimizations) |
| `-trimpath` | Remove file system paths from binary (reproducible builds) |
| `-buildmode <mode>` | Build mode: `default`, `c-archive`, `c-shared`, `plugin`, `pie` |
| `-pgo <file>` | Profile-guided optimization using CPU profile |
| `-cover` | Build with coverage instrumentation |
| `-buildvcs` | Include version control info (`true`, `false`, `auto`) |

Cross-compile for a different platform:

```bash
GOOS=windows GOARCH=amd64 go build -o myapp.exe .
```

> [!NOTE]
> Build results are cached. Subsequent builds of unchanged packages are near-instantaneous. The cache lives in `$GOCACHE` (default: `~/.cache/go-build` on Linux).

#### `go run` — Compile and Execute

Compile and run in one step — ideal for development:

```bash
go run .
```

Run a specific file:

```bash
go run main.go
```

Pass arguments to your program after `--`:

```bash
go run . -- --port 8080
```

Or simply after the package pattern:

```bash
go run . --port 8080
```

Run a remote tool directly:

```bash
go run golang.org/x/tools/cmd/stringer@latest -type=MyEnum
```

#### `go install` — Compile and Install

Install a binary to `$GOBIN`:

```bash
go install .
```

Install a tool at a specific version (no go.mod required):

```bash
go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.1
```

```text
# binary installed to $GOPATH/bin/golangci-lint
```

Install the latest version:

```bash
go install example.com/tool@latest
```

### 4.2 Testing

#### `go test` — Run Tests

Run all tests in the current package:

```bash
go test
```

```text
PASS
ok      example.com/myapp    0.042s
```

Run all tests recursively:

```bash
go test ./...
```

**Common flags:**

| Flag | Purpose |
|------|---------|
| `-v` | Verbose — print each test name and status |
| `-run <regex>` | Run only tests matching the regex |
| `-bench <regex>` | Run benchmarks matching the regex (use `.` for all) |
| `-cover` | Show coverage percentage |
| `-coverprofile <file>` | Write coverage data to file |
| `-race` | Enable race detector during tests |
| `-count <n>` | Run each test n times (use `-count=1` to bypass cache) |
| `-timeout <d>` | Fail tests after duration (default: 10m) |
| `-short` | Signal tests to skip long-running operations |
| `-fuzz <regex>` | Run fuzz tests matching regex |
| `-json` | Output results in JSON (for CI parsing) |
| `-c` | Compile test binary without running it |
| `-shuffle <mode>` | Randomize test execution order: `on`, `off`, or seed |
| `-failfast` | Stop after first test failure |
| `-parallel <n>` | Max parallel tests (default: `GOMAXPROCS`) |

Run tests with coverage and generate an HTML report:

```bash
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
```

```text
ok      example.com/myapp/pkg    0.031s    coverage: 87.3% of statements
```

Run benchmarks:

```bash
go test -bench=. -benchmem ./...
```

```text
BenchmarkSort-8     1000000    1042 ns/op    256 B/op    4 allocs/op
```

> [!TIP]
> Use `-count=1` to bypass the test cache when you need fresh results: `go test -count=1 ./...`. Go caches passing test results and reuses them when source hasn't changed.

#### Test File Conventions

Test files must end in `_test.go`. They can contain four types of test functions:

```go
func TestXxx(t *testing.T) { ... }       // Unit test
func BenchmarkXxx(b *testing.B) { ... }  // Benchmark
func FuzzXxx(f *testing.F) { ... }       // Fuzz test
func ExampleXxx() { ... }                // Testable example (checked output)
```

**Table-driven tests** — the idiomatic Go testing pattern:

```go
func TestAdd(t *testing.T) {
    tests := []struct {
        name     string
        a, b     int
        expected int
    }{
        {"positive", 1, 2, 3},
        {"negative", -1, -2, -3},
        {"zero", 0, 0, 0},
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            if got := Add(tt.a, tt.b); got != tt.expected {
                t.Errorf("Add(%d, %d) = %d, want %d", tt.a, tt.b, got, tt.expected)
            }
        })
    }
}
```

### 4.3 Dependency Management

#### `go mod init` — Initialize a Module

```bash
go mod init github.com/yourname/myproject
```

Creates `go.mod` with the module path declaration.

#### `go mod tidy` — Synchronize Dependencies

Adds missing dependencies and removes unused ones:

```bash
go mod tidy
```

This is the single most important module command. Run it after adding/removing imports or upgrading Go versions.

#### `go get` — Add or Update Dependencies

Add a dependency:

```bash
go get github.com/gin-gonic/gin@v1.9.1
```

Update to latest:

```bash
go get -u github.com/gin-gonic/gin
```

Update all direct and indirect dependencies:

```bash
go get -u ./...
```

Update only patch versions:

```bash
go get -u=patch ./...
```

Remove a dependency:

```bash
go get github.com/old/dependency@none
```

Add a tool dependency (Go 1.24+):

```bash
go get -tool golang.org/x/tools/cmd/stringer
```

**Common flags:**

| Flag | Purpose |
|------|---------|
| `-u` | Update to latest version |
| `-u=patch` | Update only patch versions |
| `-t` | Include test dependencies |
| `-tool` | Add as a tool dependency (Go 1.24+) |
| `@version` | Specify exact version: `@v1.2.3`, `@latest`, `@none` |

#### `go mod download` — Pre-fill Module Cache

```bash
go mod download
```

Downloads all modules in `go.mod` to the local cache (`$GOMODCACHE`) without building. Useful for Docker layer caching:

```dockerfile
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o /app .
```

#### `go mod vendor` — Vendor Dependencies

```bash
go mod vendor
```

Copies all dependencies into a `vendor/` directory. Build with `-mod=vendor` or set `GOFLAGS=-mod=vendor`.

#### `go mod graph` — Show Dependency Graph

```bash
go mod graph
```

```text
example.com/myapp golang.org/x/sync@v0.7.0
example.com/myapp github.com/gin-gonic/gin@v1.9.1
golang.org/x/sync@v0.7.0 golang.org/x/net@v0.25.0
```

#### `go mod verify` — Verify Checksums

```bash
go mod verify
```

```text
all modules verified
```

Checks that downloaded modules match the expected checksums in `go.sum`.

#### `go mod why` — Explain Why a Module Is Needed

```bash
go mod why golang.org/x/net
```

```text
# golang.org/x/net
example.com/myapp
github.com/gin-gonic/gin
golang.org/x/net/html
```

#### `go mod edit` — Programmatic go.mod Editing

```bash
go mod edit -require=github.com/pkg/errors@v0.9.1
go mod edit -replace=example.com/mod=../local-mod
go mod edit -json
```

### 4.4 Code Quality

#### `go vet` — Static Analysis

Run the default set of analyzers:

```bash
go vet ./...
```

Vet catches common mistakes like: Printf format-argument mismatches, unreachable code, incorrect struct tags, suspicious mutex copies, and more.

**Flags:**

| Flag | Purpose |
|------|---------|
| `-json` | Output results in JSON |
| `-vettool <binary>` | Use an external analyzer binary |

> [!WARNING]
> `go vet` is not a linter — it focuses on correctness bugs, not style. For comprehensive linting, consider tools like `golangci-lint` which runs `go vet` plus dozens of additional analyzers.

#### `go fmt` — Format Code

Format all Go files in the current package:

```bash
go fmt ./...
```

This runs `gofmt -l -w` on each file, applying the canonical Go formatting style. There is no configuration — every Go project uses the same format.

#### `go fix` — Apply Code Fixes

```bash
go fix ./...
```

Automatically updates code to use newer Go APIs when they replace deprecated ones. Typically run after upgrading Go versions.

### 4.5 Information and Documentation

#### `go doc` — View Documentation

View package documentation:

```bash
go doc fmt
```

View a specific function:

```bash
go doc fmt.Println
```

Show all symbols (including unexported with `-u`):

```bash
go doc -all fmt
```

View source code:

```bash
go doc -src fmt.Println
```

Start a local documentation server:

```bash
go doc -http=:6060
```

#### `go list` — List Packages and Modules

List all packages in the current module:

```bash
go list ./...
```

List with custom format:

```bash
go list -f '{{.ImportPath}} {{.GoFiles}}' ./...
```

List module information:

```bash
go list -m -json all
```

Check for available updates:

```bash
go list -m -u all
```

```text
golang.org/x/sync v0.7.0 [v0.8.0]
```

List all versions of a module:

```bash
go list -m -versions golang.org/x/sync
```

```text
golang.org/x/sync v0.0.0-20171101214715-fd80eb99c8f6 v0.1.0 v0.2.0 ... v0.8.0
```

#### `go version` — Print Version Information

```bash
go version
```

```text
go version go1.24.2 linux/amd64
```

Inspect a compiled binary:

```bash
go version -m ./myapp
```

```text
./myapp: go1.24.2
    path    example.com/myapp
    mod     example.com/myapp    (devel)
    dep     golang.org/x/sync    v0.7.0    h1:YsImfS...=
    build   -compiler=gc
    build   GOOS=linux
    build   GOARCH=amd64
    build   -ldflags=-s -w
```

#### `go env` — Environment Information

```bash
go env
go env -json GOOS GOARCH
go env -changed
```

### 4.6 Code Generation

#### `go generate` — Run Directives

Process `//go:generate` directives in Go source files:

```bash
go generate ./...
```

A directive looks like:

```go
//go:generate stringer -type=Pill
```

Available variables in generate directives:

| Variable | Value |
|----------|-------|
| `$GOARCH` | Target architecture |
| `$GOOS` | Target operating system |
| `$GOFILE` | Name of the file containing the directive |
| `$GOLINE` | Line number of the directive |
| `$GOPACKAGE` | Package name of the file |
| `$GOROOT` | Go root directory |
| `$DOLLAR` | A literal `$` sign |

> [!NOTE]
> `go generate` is never run automatically by `go build`. It is a separate development-time step. Generated files should be committed to version control.

### 4.7 Workspaces

Workspaces let you work with multiple modules simultaneously without `replace` directives.

#### `go work init` — Create a Workspace

```bash
go work init ./module-a ./module-b
```

Creates a `go.work` file:

```go
go 1.24.2

use (
    ./module-a
    ./module-b
)
```

#### `go work use` — Add Modules

```bash
go work use ./module-c
```

#### `go work sync` — Synchronize Build List

```bash
go work sync
```

Syncs the workspace's build list back into each module's `go.mod`.

#### `go work edit` — Edit go.work Programmatically

```bash
go work edit -use=./new-module
go work edit -json
```

#### `go work vendor` — Vendor Workspace Dependencies

```bash
go work vendor
```

### 4.8 Other Commands

#### `go clean` — Remove Cached Files

```bash
go clean                   # Remove build artifacts in current dir
go clean -cache            # Clear entire build cache
go clean -testcache        # Clear test result cache
go clean -modcache         # Clear module download cache
go clean -fuzzcache        # Clear fuzz test cache
```

> [!CAUTION]
> `go clean -modcache` deletes ALL downloaded modules across all projects. This requires re-downloading dependencies for every project on next build. Use only when you need to reclaim disk space or fix a corrupted cache.

#### `go telemetry` — Manage Telemetry

```bash
go telemetry              # Show current mode
go telemetry off          # Disable telemetry
go telemetry local        # Collect locally only (default)
go telemetry on           # Upload anonymized usage data
```

#### `go tool` — Run Low-Level Tools

Access bundled tools:

```bash
go tool                   # List available tools
go tool compile           # Go compiler
go tool link              # Go linker
go tool asm               # Go assembler
go tool cgo               # C/Go bridge
go tool cover             # Coverage analysis
go tool trace             # Execution tracer
go tool pprof             # Profile viewer
go tool nm                # Symbol table
go tool objdump           # Disassembler
go tool addr2line         # Address-to-line mapping
```

Run the CPU profiler on a profile file:

```bash
go tool pprof -http=:8080 cpu.prof
```

View an execution trace:

```bash
go tool trace trace.out
```

#### `go bug` — File a Bug Report

```bash
go bug
```

Opens a pre-filled issue template in your browser with your system information.

---

## 5. Common Tasks

### 5.1 Create a New Project

**Goal:** Start a new Go project from scratch.

**Steps:**

```bash
mkdir myproject && cd myproject
go mod init github.com/yourname/myproject
```

Create `main.go`:

```go
package main

import "fmt"

func main() {
    fmt.Println("Hello from myproject!")
}
```

**Verify:**

```bash
go run .
```

```text
Hello from myproject!
```

**If it fails:** Ensure `go` is in your `PATH` (`go version`). Check that the module path is valid (no spaces, follows Go module naming conventions).

### 5.2 Add a Dependency

**Goal:** Import and use an external package.

**Steps:**

```bash
go get github.com/google/uuid@latest
```

Use it in code:

```go
import "github.com/google/uuid"

id := uuid.New()
```

Then tidy:

```bash
go mod tidy
```

**Verify:** `go build .` succeeds without errors.

**If it fails:** Check network connectivity. If behind a firewall, set `GOPROXY=direct` or configure a private proxy.

### 5.3 Update All Dependencies

**Goal:** Bring all dependencies to their latest versions.

**Steps:**

```bash
go get -u ./...
go mod tidy
```

For conservative updates (patch versions only):

```bash
go get -u=patch ./...
go mod tidy
```

**Verify:**

```bash
go build ./...
go test ./...
```

**If it fails:** A dependency may have introduced a breaking change. Check `go list -m -u all` for the specific version jump and review the changelog.

### 5.4 Run Tests with Coverage

**Goal:** Measure test coverage across your project.

**Steps:**

```bash
go test -coverprofile=coverage.out ./...
go tool cover -func=coverage.out
```

```text
example.com/myapp/pkg/handler.go:15:    HandleRequest    100.0%
example.com/myapp/pkg/handler.go:42:    ParseInput       75.0%
total:                                  (statements)     87.3%
```

Generate an HTML report:

```bash
go tool cover -html=coverage.out -o coverage.html
```

**Verify:** Open `coverage.html` in a browser. Green = covered, red = uncovered.

### 5.5 Cross-Compile for Different OS/Architecture

**Goal:** Build binaries for platforms other than your own.

**Steps:**

```bash
# Linux AMD64
GOOS=linux GOARCH=amd64 go build -o myapp-linux-amd64 .

# Windows AMD64
GOOS=windows GOARCH=amd64 go build -o myapp-windows-amd64.exe .

# macOS ARM64 (Apple Silicon)
GOOS=darwin GOARCH=arm64 go build -o myapp-darwin-arm64 .

# Linux ARM (Raspberry Pi)
GOOS=linux GOARCH=arm GOARM=7 go build -o myapp-linux-armv7 .
```

**Verify:**

```bash
file myapp-linux-amd64
```

```text
myapp-linux-amd64: ELF 64-bit LSB executable, x86-64, ...
```

**If it fails:** If your code uses cgo, set `CGO_ENABLED=0` for pure Go builds or install the target's C cross-compiler.

> [!TIP]
> See all supported platform combinations with `go tool dist list`. As of Go 1.24, there are 80+ supported `GOOS/GOARCH` pairs.

### 5.6 Build a Static Binary

**Goal:** Create a fully static binary with no dynamic library dependencies.

**Steps:**

```bash
CGO_ENABLED=0 go build -ldflags='-s -w' -o myapp .
```

- `CGO_ENABLED=0` — disable cgo, removing glibc dependency
- `-s` — strip symbol table
- `-w` — strip DWARF debug info

**Verify:**

```bash
ldd myapp
```

```text
not a dynamic executable
```

### 5.7 Use Build Tags

**Goal:** Conditionally compile code based on tags.

Create a file `feature_premium.go`:

```go
//go:build premium

package main

func premiumFeature() string {
    return "Premium enabled"
}
```

Create the default fallback `feature_default.go`:

```go
//go:build !premium

package main

func premiumFeature() string {
    return "Premium not available"
}
```

Build with the tag:

```bash
go build -tags=premium -o myapp .
```

### 5.8 Profile a Program (CPU, Memory)

**Goal:** Find performance bottlenecks.

**Steps — CPU profile via test:**

```bash
go test -cpuprofile=cpu.prof -bench=. ./...
go tool pprof -http=:8080 cpu.prof
```

**Steps — Memory profile:**

```bash
go test -memprofile=mem.prof -bench=. ./...
go tool pprof -http=:8080 mem.prof
```

**Steps — Runtime profiling with `net/http/pprof`:**

```go
import _ "net/http/pprof"
// Then: go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
```

### 5.9 Write and Run Benchmarks

**Goal:** Measure function performance.

Create `sort_test.go`:

```go
func BenchmarkSort(b *testing.B) {
    data := make([]int, 1000)
    for i := range data {
        data[i] = 1000 - i
    }
    b.ResetTimer()
    for b.Loop() {
        slices.Sort(data)
    }
}
```

Run:

```bash
go test -bench=BenchmarkSort -benchmem -count=5 ./...
```

```text
BenchmarkSort-8   154032   7812 ns/op   0 B/op   0 allocs/op
```

Compare results across changes using `benchstat`:

```bash
go install golang.org/x/perf/cmd/benchstat@latest
go test -bench=. -count=10 ./... > old.txt
# ... make changes ...
go test -bench=. -count=10 ./... > new.txt
benchstat old.txt new.txt
```

### 5.10 Use go generate

**Goal:** Auto-generate code from directives.

Add a directive to your Go source:

```go
//go:generate stringer -type=Color

type Color int

const (
    Red Color = iota
    Green
    Blue
)
```

Install the tool and run:

```bash
go install golang.org/x/tools/cmd/stringer@latest
go generate ./...
```

This creates `color_string.go` with a `String()` method for your enum.

### 5.11 Embed Files with go:embed

**Goal:** Bundle static files (HTML, SQL, configs) into your binary.

```go
package main

import (
    "embed"
    "fmt"
)

//go:embed templates/*.html
var templates embed.FS

//go:embed version.txt
var version string

func main() {
    fmt.Println("Version:", version)
    data, _ := templates.ReadFile("templates/index.html")
    fmt.Println(string(data))
}
```

Build normally — embedded files are included automatically:

```bash
go build -o myapp .
```

### 5.12 Use Workspaces for Multi-Module Development

**Goal:** Develop multiple interdependent modules locally without publishing.

```bash
mkdir workspace && cd workspace
git clone https://github.com/yourorg/lib.git
git clone https://github.com/yourorg/app.git
go work init ./lib ./app
```

Now `app` automatically uses your local `lib` changes without `replace` directives. Build and test across modules:

```bash
go build ./...
go test ./...
```

### 5.13 Vendor Dependencies

**Goal:** Include all dependencies in your repository for hermetic builds.

```bash
go mod vendor
go build -mod=vendor .
```

To always use vendor:

```bash
go env -w GOFLAGS=-mod=vendor
```

**Verify:** The `vendor/` directory contains all dependency source code and a `vendor/modules.txt` manifest.

### 5.14 Use the Race Detector

**Goal:** Find data races in concurrent code.

```bash
go test -race ./...
go run -race .
go build -race -o myapp .
```

```text
WARNING: DATA RACE
Read at 0x00c0000a4020 by goroutine 7:
  main.readCounter()
      /home/user/main.go:15 +0x38
Previous write at 0x00c0000a4020 by goroutine 6:
  main.incrementCounter()
      /home/user/main.go:11 +0x48
```

> [!WARNING]
> The race detector adds significant overhead (~2x CPU, ~5-10x memory). Use it during testing and development, not in production binaries.

### 5.15 Debug with Delve

**Goal:** Step-debug a Go program.

Install Delve:

```bash
go install github.com/go-delve/delve/cmd/dlv@latest
```

Start debugging:

```bash
dlv debug .
```

```text
Type 'help' for list of commands.
(dlv) break main.main
(dlv) continue
(dlv) next
(dlv) print myVar
(dlv) goroutines
```

Debug a test:

```bash
dlv test -- -run TestMyFunction
```

### 5.16 Use Profile-Guided Optimization (PGO)

**Goal:** Improve performance using real-world profiling data.

**Steps:**

1. Collect a CPU profile from production or representative load:

```bash
curl -o default.pgo http://localhost:6060/debug/pprof/profile?seconds=30
```

2. Place the profile in the main package directory as `default.pgo`:

```bash
mv default.pgo ./cmd/myapp/default.pgo
```

3. Build — PGO is applied automatically when `default.pgo` exists:

```bash
go build -o myapp ./cmd/myapp
```

Or specify explicitly:

```bash
go build -pgo=cpu.pgo -o myapp .
```

PGO typically improves performance by 2-7% with no code changes.

### 5.17 Build C-Compatible Libraries

**Goal:** Create libraries callable from C, Python, Ruby, etc.

**C static archive:**

```go
package main

import "C"

//export Add
func Add(a, b C.int) C.int {
    return a + b
}

func main() {}
```

```bash
go build -buildmode=c-archive -o libmath.a .
```

**C shared library:**

```bash
go build -buildmode=c-shared -o libmath.so .
```

Both produce a header file (`libmath.h`) for C consumers.

### 5.18 Pin a Specific Go Toolchain Version

**Goal:** Ensure everyone on the team uses the same Go version.

Add the `toolchain` directive to `go.mod`:

```go
module example.com/myapp

go 1.24.2
toolchain go1.24.2
```

Or set the policy:

```bash
go env -w GOTOOLCHAIN=go1.24.2
```

With `GOTOOLCHAIN=auto` (the default), Go automatically downloads the required toolchain version if your local one is older.

### 5.19 Use GOPRIVATE for Private Repositories

**Goal:** Fetch modules from private Git repositories.

```bash
go env -w GOPRIVATE=github.com/mycompany/*,gitlab.internal.com/*
```

Configure Git for authentication:

```bash
git config --global url."https://oauth2:${GITLAB_TOKEN}@gitlab.internal.com/".insteadOf "https://gitlab.internal.com/"
```

Or use SSH:

```bash
git config --global url."git@github.com:".insteadOf "https://github.com/"
```

### 5.20 Create and Run Fuzz Tests

**Goal:** Discover edge-case bugs with automated fuzzing.

```go
func FuzzParseJSON(f *testing.F) {
    // Seed corpus
    f.Add([]byte(`{"key": "value"}`))
    f.Add([]byte(`{}`))
    f.Add([]byte(`[]`))

    f.Fuzz(func(t *testing.T, data []byte) {
        var result map[string]any
        if err := json.Unmarshal(data, &result); err != nil {
            return // Invalid input is fine
        }
        // Re-marshal and check round-trip
        out, err := json.Marshal(result)
        if err != nil {
            t.Fatalf("Marshal failed: %v", err)
        }
        var result2 map[string]any
        if err := json.Unmarshal(out, &result2); err != nil {
            t.Fatalf("Round-trip failed: %v", err)
        }
    })
}
```

Run fuzzing for a duration:

```bash
go test -fuzz=FuzzParseJSON -fuzztime=30s ./...
```

```text
fuzz: elapsed: 30s, execs: 142857 (4762/sec), new interesting: 12
PASS
```

Failing inputs are saved to `testdata/fuzz/FuzzParseJSON/` and replayed automatically on subsequent test runs.

### 5.21 Use `go test -json` for CI

**Goal:** Machine-parseable test output for CI pipelines.

```bash
go test -json ./... 2>&1 | tee test-results.json
```

Each line is a JSON object:

```json
{"Time":"2026-05-07T10:00:00Z","Action":"pass","Package":"example.com/myapp","Test":"TestAdd","Elapsed":0.001}
```

Use `gotestsum` for better CI integration:

```bash
go install gotest.tools/gotestsum@latest
gotestsum --junitfile results.xml ./...
```

### 5.22 Build Reproducible Binaries with `-trimpath`

**Goal:** Produce identical binaries regardless of the build machine's file layout.

```bash
go build -trimpath -ldflags='-s -w' -o myapp .
```

The `-trimpath` flag removes local file paths from the binary. Combined with version-pinned dependencies (`go.sum`) and a pinned toolchain, builds are reproducible across machines.

### 5.23 Inject Version Info with `-ldflags`

**Goal:** Stamp build metadata into your binary at compile time.

```go
package main

var (
    version = "dev"
    commit  = "none"
    date    = "unknown"
)

func main() {
    fmt.Printf("myapp %s (commit: %s, built: %s)\n", version, commit, date)
}
```

Build with values:

```bash
go build -ldflags="-X main.version=1.2.3 -X main.commit=$(git rev-parse HEAD) -X main.date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" -o myapp .
```

```text
myapp 1.2.3 (commit: abc123def, built: 2026-05-07T10:00:00Z)
```

### 5.24 Use WebAssembly

**Goal:** Run Go in the browser.

```bash
GOOS=js GOARCH=wasm go build -o main.wasm .
```

Copy the JavaScript support file:

```bash
cp "$(go env GOROOT)/lib/wasm/wasm_exec.js" .
```

Create `index.html`:

```html
<html>
<head><script src="wasm_exec.js"></script></head>
<body>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject)
    .then(result => go.run(result.instance));
</script>
</body>
</html>
```

Alternatively, target WASI:

```bash
GOOS=wasip1 GOARCH=wasm go build -o main.wasm .
```

### 5.25 Use Build Caching Effectively

**Goal:** Understand and manage Go's build cache.

View cache location:

```bash
go env GOCACHE
```

```text
/home/user/.cache/go-build
```

Clear the build cache:

```bash
go clean -cache
```

Clear test cache only:

```bash
go clean -testcache
```

View cache size:

```bash
du -sh $(go env GOCACHE)
```

The build cache is safe to delete at any time — it's purely a performance optimization.

---

## 6. Troubleshooting

### Error: `cannot find module providing package example.com/foo`

**Cause:** The dependency is not in your `go.mod` or the module proxy cannot find it.

**Solution:**

```bash
go get example.com/foo@latest
go mod tidy
```

If the module is private, ensure `GOPRIVATE` is set:

```bash
go env -w GOPRIVATE=example.com/*
```

**Prevention:** Always run `go mod tidy` after adding new imports.

---

### Error: `verifying module: checksum mismatch`

**Cause:** The downloaded module content doesn't match what `go.sum` records. This can happen when a module author retracts and re-publishes the same version (a violation of module semantics) or when using a misconfigured proxy.

**Solution:**

1. If you trust the source, delete the stale entry from `go.sum` and re-fetch:

```bash
go mod tidy
```

2. If that fails, clear the module cache:

```bash
go clean -modcache
go mod download
```

**Prevention:** Never manually edit `go.sum`. Let Go tooling manage it.

---

### Error: `SECURITY ERROR - checksum mismatch` from sum database

**Cause:** The checksum database (`sum.golang.org`) reports a different checksum than what you downloaded. This could indicate a compromised module or network interference.

**Solution:** Verify the module's authenticity. If it's a private module:

```bash
go env -w GONOSUMDB=example.com/*
go env -w GOPRIVATE=example.com/*
```

If you trust the module:

```bash
go clean -modcache
go mod download
```

**Prevention:** Use `GOPRIVATE` for all internal modules from the start.

---

### Error: `module declares its path as "X" but was required as "Y"`

**Cause:** The `module` directive in the dependency's `go.mod` doesn't match the import path you used. This typically happens with forks or vanity import paths.

**Solution:** Use the path declared in the module's `go.mod`, or add a `replace` directive:

```bash
go mod edit -replace=Y=X@version
```

**Prevention:** Check the module's `go.mod` before adding it as a dependency.

---

### Error: `WARNING: DATA RACE` during test execution

**Cause:** Two goroutines access the same variable concurrently without synchronization, and at least one access is a write.

**Solution:** Add proper synchronization:

- Use `sync.Mutex` or `sync.RWMutex` for shared state
- Use channels for communication between goroutines
- Use `sync/atomic` for simple counters and flags

**Prevention:** Always run `go test -race ./...` in CI.

---

### Error: `gcc: exec: "gcc": executable file not found in $PATH`

**Cause:** Your code (or a dependency) uses cgo, which requires a C compiler. `CGO_ENABLED=1` (the default) but no C compiler is installed.

**Solution:**

Install a C compiler:
- **Linux:** `sudo apt install gcc` or `sudo dnf install gcc`
- **macOS:** `xcode-select --install`
- **Windows:** Install [MinGW-w64](https://www.mingw-w64.org/) or [TDM-GCC](https://jmeubank.github.io/tdm-gcc/)

Or disable cgo if you don't need C interop:

```bash
CGO_ENABLED=0 go build .
```

**Prevention:** Set `CGO_ENABLED=0` in CI/Docker builds when you don't need cgo.

---

### Error: `permission denied` accessing module cache

**Cause:** The module cache directory (`$GOMODCACHE`, default `$GOPATH/pkg/mod`) has incorrect permissions, often caused by running `go` as root and then as a regular user.

**Solution:**

```bash
sudo chown -R $(whoami):$(whoami) $(go env GOMODCACHE)
```

Or clear and rebuild:

```bash
sudo go clean -modcache
go mod download
```

**Prevention:** Never run `go` commands as root. Use `-mod=vendor` in Docker containers.

---

### Error: `test timed out after 10m0s`

**Cause:** A test or the entire test suite took longer than the default 10-minute timeout.

**Solution:** Increase the timeout:

```bash
go test -timeout 30m ./...
```

Or fix the slow test — look for:
- Tests waiting on network calls that hang
- Infinite loops or deadlocks
- Tests that don't respect the `-short` flag

**Prevention:** Use `testing.Short()` to skip long tests:

```go
if testing.Short() {
    t.Skip("skipping long test in short mode")
}
```

---

### Error: `import cycle not allowed`

**Cause:** Package A imports package B which imports package A (directly or transitively).

**Solution:** Break the cycle by:
1. Moving shared types to a separate package
2. Using interfaces to invert the dependency
3. Merging the tightly-coupled packages

Find the cycle:

```bash
go vet ./...
```

**Prevention:** Keep package dependencies acyclic. Design packages around behaviors, not objects.

---

### Error: `build constraints exclude all Go files in /path/to/pkg`

**Cause:** All `.go` files in the package have build constraints (`//go:build`) that exclude your current `GOOS`/`GOARCH` combination, or the package requires a build tag you haven't specified.

**Solution:**

Check file headers for build constraints. If the package requires a tag:

```bash
go build -tags=required_tag ./...
```

If cross-compiling, verify you're targeting the right platform:

```bash
go env GOOS GOARCH
```

**Prevention:** Document required build tags in your README.

---

### Error: GOPATH vs GOROOT confusion

**Cause:** `GOROOT` is set to `GOPATH` or vice versa, or `GOROOT` points to the wrong directory.

**Solution:**

```bash
go env GOROOT GOPATH
```

- `GOROOT` should point to the Go installation (e.g., `/usr/local/go`)
- `GOPATH` should point to your workspace (e.g., `$HOME/go`)

Reset to defaults:

```bash
go env -u GOROOT
go env -u GOPATH
```

**Prevention:** Don't set `GOROOT` manually. The `go` command infers it from its own location.

---

### Error: `go: updates to go.mod needed`

**Cause:** You're in a module-aware directory but `go.mod` is out of sync with your imports. Running `go` commands in read-only module mode (e.g., `GOFLAGS=-mod=readonly`) prevents automatic updates.

**Solution:**

```bash
go mod tidy
```

**Prevention:** Run `go mod tidy` after any import changes. In CI, use `-mod=readonly` to catch untidy modules.

---

### Error: proxy/network issues with GOPROXY

**Cause:** The module proxy is unreachable, blocked by a firewall, or returning errors.

**Solution:**

Try fetching directly:

```bash
GOPROXY=direct go get example.com/module@latest
```

Or switch to a different proxy:

```bash
go env -w GOPROXY=https://goproxy.io,direct
```

Check if the module exists on the proxy:

```bash
curl https://proxy.golang.org/example.com/module/@latest
```

**Prevention:** For air-gapped environments, use `go mod vendor` and build with `-mod=vendor`.

---

### Error: `invalid version: unknown revision`

**Cause:** The version specified in `go.mod` or `go get` doesn't exist in the module's repository. This can happen when a tag is deleted or when using a pseudo-version for a non-existent commit.

**Solution:**

Check available versions:

```bash
go list -m -versions example.com/module
```

Update to a valid version:

```bash
go get example.com/module@latest
```

**Prevention:** Use tagged versions rather than pseudo-versions when possible.

---

### Issue: Flaky test failures

**Cause:** Tests that pass inconsistently due to race conditions, timing dependencies, shared state, or environmental assumptions. Common across large Go projects (golang/go issues #76540, #65293, #67599, #73820).

**Solution:**

- Run with `-race` to detect data races
- Use `-count=5` or higher to reproduce intermittent failures
- Use `-shuffle=on` to detect order-dependent tests
- Isolate shared state with `t.TempDir()` and unique ports
- Use `t.Parallel()` carefully — ensure tests don't share mutable state

```bash
go test -race -count=10 -shuffle=on -v ./...
```

**Prevention:** Design tests to be hermetic — each test should set up and tear down its own state.

---

### Issue: Binary size too large

**Cause:** Go binaries include the runtime, garbage collector, and all imported packages. Default builds include debug symbols and DWARF info.

**Solution:**

Strip debug info:

```bash
go build -ldflags='-s -w' -o myapp .
```

Use `upx` for further compression (at the cost of startup time):

```bash
upx --best myapp
```

Analyze what's consuming space:

```bash
go build -o myapp .
go tool nm -size myapp | sort -n -r | head -20
```

**Prevention:** Audit imports — each imported package adds to binary size. Avoid large dependencies for small features.

---

### Error: `undefined: SomeFunction` after upgrading Go version

**Cause:** A function or type was moved, renamed, or removed in the new Go version, or a build constraint now excludes the file containing it.

**Solution:**

1. Check the [Go release notes](https://go.dev/doc/devel/release) for breaking changes
2. Run `go fix ./...` to apply automated fixes
3. Check build constraints in the affected files

**Prevention:** Read release notes before upgrading. Test thoroughly with `go test ./...` after any version change.

---

### Error: `module not found in vendor`

**Cause:** The `vendor/` directory is out of sync with `go.mod`. A dependency was added or updated without re-vendoring.

**Solution:**

```bash
go mod vendor
go build -mod=vendor .
```

**Prevention:** Always run `go mod vendor` after `go get` or `go mod tidy` when using vendor mode.

---

### Error: WebAssembly `wasm_exec.js` errors

**Cause:** The `wasm_exec.js` support file doesn't match the Go version used to compile the `.wasm` binary. Each Go version ships its own `wasm_exec.js`.

**Solution:**

Always copy `wasm_exec.js` from the same Go version used for compilation:

```bash
cp "$(go env GOROOT)/lib/wasm/wasm_exec.js" .
GOOS=js GOARCH=wasm go build -o main.wasm .
```

For WASI targets (`GOOS=wasip1`), use `wasm_exec_node.js` from the same location.

**Prevention:** Automate the copy step in your build script so it stays in sync with Go upgrades.

---

### Error: `corrupt zip file` for timezone data

**Cause:** The embedded timezone database is corrupted, or the system timezone data is missing. Common in minimal Docker images.

**Solution:**

Install timezone data:

```bash
# Alpine
apk add tzdata

# Debian/Ubuntu
apt install tzdata
```

Or embed timezone data in the binary:

```go
import _ "time/tzdata"
```

**Prevention:** Use `import _ "time/tzdata"` when deploying to minimal containers.

---

### Error: `connection is shut down` (net/rpc)

**Cause:** The RPC client is using a connection that was closed by the server or lost due to a network issue. The `net/rpc` package does not reconnect automatically.

**Solution:**

Implement reconnection logic in your client. Check `client.Call()` errors and create a new client when the connection is lost.

Note: `net/rpc` is frozen — no new features will be added. Consider using gRPC or a similar framework for new projects.

**Prevention:** Use connection health checks and implement retry logic with backoff.

---

### Issue: Test caching surprises

**Cause:** `go test` caches passing results and skips re-execution when source hasn't changed. This can mask failures caused by external state (database, time, network).

**Solution:**

Bypass the cache:

```bash
go test -count=1 ./...
```

Or clear the test cache:

```bash
go clean -testcache
```

**Prevention:** Tests that depend on external state should call `t.Setenv()` or use test helpers that change the test's inputs, which automatically invalidates the cache.

---

### Issue: `go vet` false positives

**Cause:** `go vet` reports issues that are intentional in your code (e.g., intentionally unused results, certain struct tag patterns).

**Solution:**

Suppress specific analyzers:

```bash
go vet -composites=false ./...
```

Or use a `//nolint` directive if using `golangci-lint`, which wraps `go vet`.

Note that `go vet` itself doesn't support inline suppression — if an analyzer is too noisy, disable it. However, most `go vet` warnings are genuine bugs.

**Prevention:** Investigate each warning before suppressing. `go vet` has a very low false-positive rate.

---

### Issue: `go generate` not running

**Cause:** The `//go:generate` directive has a syntax error (e.g., space between `//` and `go:generate`), the required tool isn't installed, or you're running `go generate` in the wrong directory.

**Solution:**

Check the directive syntax — it must be exactly `//go:generate` with no space:

```go
//go:generate stringer -type=MyEnum   // CORRECT
// go:generate stringer -type=MyEnum  // WRONG — space before 'go'
```

Ensure the tool is installed:

```bash
which stringer || go install golang.org/x/tools/cmd/stringer@latest
```

Run in the right directory:

```bash
go generate ./...  # recursive from current module root
```

**Prevention:** Use `go generate -v ./...` to see which directives are being processed.

---

### Issue: `go.work` workspace problems

**Cause:** Workspace mode (`go.work`) conflicts with `go.mod` replace directives or CI builds that don't expect a workspace.

**Solution:**

Disable workspace mode for CI:

```bash
GOWORK=off go build ./...
```

Or remove `go.work` from version control and document it as a local development tool.

Check which workspace is active:

```bash
go env GOWORK
```

**Prevention:** Add `go.work` and `go.work.sum` to `.gitignore` if workspaces are developer-local only.

---

## 7. FAQ

### General

**What is Go?**

Go is an open-source programming language designed at Google by Robert Griesemer, Rob Pike, and Ken Thompson. First released in 2009 (Go 1.0 in 2012), it is a compiled, statically typed language built for systems programming, cloud services, and concurrent applications. The golang/go repository contains the entire language implementation: compiler, runtime, standard library, and toolchain.

**Why choose Go over other languages?**

Go excels when you need: fast compilation (large projects build in seconds), reliable concurrent programming (goroutines are simpler than threads), easy deployment (single static binary), or strong standard library coverage (HTTP, JSON, crypto, databases built in). It deliberately avoids complexity — no generics inheritance hierarchy, no exceptions, no implicit behavior.

**What is Go NOT good for?**

Go is not ideal for: GUI desktop applications (limited native GUI support), embedded systems with extreme memory constraints (garbage collector overhead), heavy numerical computing (Python/NumPy or Julia are better), or scripting one-liners (too verbose for trivial scripts).

**Is Go "Golang"?**

"Go" is the official name. "Golang" is the commonly used search-friendly name (since "Go" is hard to search for). The domain is `go.dev`, the module path prefix is `golang.org`, and the repository is `github.com/golang/go`.

---

### Installation

**How do I install multiple Go versions?**

Use the version-specific installer pattern:

```bash
go install golang.org/dl/go1.22.0@latest
go1.22.0 download
go1.22.0 version
```

Each version installs independently under `$HOME/sdk/`. You can switch your default by adjusting `GOTOOLCHAIN` or your `PATH`.

**What's the difference between GOROOT and GOPATH?**

`GOROOT` is where Go itself is installed — the compiler, standard library source, and tools. You should almost never set it manually. `GOPATH` is your workspace — where `go install` puts binaries (`$GOPATH/bin`) and the module cache lives (`$GOPATH/pkg/mod`). With modules (Go 1.11+), you no longer need to work inside `$GOPATH`.

**Can I use Go without setting any environment variables?**

Yes. The defaults work out of the box for most users. The Go installer sets `GOROOT` implicitly, `GOPATH` defaults to `$HOME/go`, and the default `GOPROXY` (proxy.golang.org) serves most public modules. You only need to configure environment variables for private modules, cross-compilation, or custom setups.

---

### Modules

**What is `go.sum` and should I commit it?**

`go.sum` contains cryptographic checksums for every version of every module your project depends on (direct and indirect). It ensures that future downloads produce the exact same code. Yes, commit it to version control — it's essential for reproducible builds and security.

**How do I use `replace` in go.mod?**

`replace` redirects a module to a different location — typically a local path during development or a fork:

```go
// Use a local copy during development
replace github.com/original/pkg => ../my-local-pkg

// Use a fork
replace github.com/original/pkg => github.com/myfork/pkg v1.2.3
```

Run `go mod edit -replace` to add replacements from the command line. Remember to remove `replace` directives before publishing your module.

**How do I depend on private modules?**

Set `GOPRIVATE` to a comma-separated list of module path prefixes:

```bash
go env -w GOPRIVATE=github.com/mycompany/*,go.internal.corp/*
```

This tells Go to skip the public proxy and checksum database for those modules. You'll also need to configure Git authentication (SSH keys or tokens) for the hosting service.

**What does `go mod tidy` actually do?**

It adds `require` directives for any imported packages not yet in `go.mod`, removes `require` directives for packages no longer imported, and updates `go.sum` with checksums for all dependencies. It's the single command that synchronizes your module metadata with your actual code.

**How do I downgrade or pin a dependency version?**

Specify the exact version:

```bash
go get example.com/module@v1.2.3
```

To remove a dependency entirely:

```bash
go get example.com/module@none
go mod tidy
```

---

### Building

**How does Go handle static linking?**

By default, Go produces statically linked binaries when cgo is disabled. With `CGO_ENABLED=0`, the resulting binary has zero external dependencies:

```bash
CGO_ENABLED=0 go build -o myapp .
```

When cgo is enabled (default on native builds), the binary dynamically links to the system C library. To force static linking with cgo:

```bash
CGO_ENABLED=1 go build -ldflags '-linkmode external -extldflags "-static"' -o myapp .
```

**How does cross-compilation work?**

Set `GOOS` and `GOARCH` before building:

```bash
GOOS=linux GOARCH=arm64 go build -o myapp .
```

Go includes a cross-compiler for every supported platform. No additional toolchains needed for pure Go code. If your code uses cgo, you'll need a C cross-compiler for the target.

**What are build tags and how do I use them?**

Build tags (build constraints) control which files are included in a build. The modern syntax uses `//go:build` at the top of a file:

```go
//go:build linux && amd64
```

Common uses: platform-specific code, optional features, integration tests. Specify tags at build time with `-tags`:

```bash
go build -tags=integration,premium ./...
```

**What's the difference between `go build` and `go install`?**

`go build` compiles and writes the binary to the current directory (or `-o` path). `go install` compiles and writes the binary to `$GOBIN` (default: `$GOPATH/bin`). Use `go build` for project binaries, `go install` for tools you want globally available.

---

### Testing

**How do I measure test coverage?**

```bash
go test -cover ./...                            # Summary
go test -coverprofile=c.out ./...               # Write profile
go tool cover -func=c.out                        # Per-function breakdown
go tool cover -html=c.out                        # HTML report
```

For coverage across the entire binary (not just unit tests), use the `-cover` flag with `go build`:

```bash
go build -cover -o myapp .
GOCOVERDIR=/tmp/coverage ./myapp
go tool covdata textfmt -i=/tmp/coverage -o coverage.out
```

**How do benchmarks work?**

Benchmark functions start with `Benchmark` and take a `*testing.B`:

```go
func BenchmarkFoo(b *testing.B) {
    for b.Loop() {
        Foo()
    }
}
```

Run with `go test -bench=.`. The test framework automatically determines how many iterations to run for stable timing. Use `-benchmem` for allocation statistics.

**What is fuzz testing?**

Fuzz testing (Go 1.18+) automatically generates random inputs to find bugs. A fuzz function provides seed inputs, and Go's fuzzer mutates them to find edge cases. Failures are saved to `testdata/fuzz/` and replayed as regression tests.

```bash
go test -fuzz=FuzzMyFunc -fuzztime=1m ./...
```

**How do table-driven tests work?**

Table-driven tests are the idiomatic Go pattern for testing multiple inputs. Define a slice of test cases, then loop through them with `t.Run()` for named subtests:

```go
tests := []struct{ name string; in, want int }{
    {"positive", 5, 10},
    {"zero", 0, 0},
}
for _, tt := range tests {
    t.Run(tt.name, func(t *testing.T) {
        if got := Double(tt.in); got != tt.want {
            t.Errorf("got %d, want %d", got, tt.want)
        }
    })
}
```

**How do I skip tests conditionally?**

```go
func TestRequiresNetwork(t *testing.T) {
    if testing.Short() {
        t.Skip("skipping network test in short mode")
    }
    // ...
}
```

Run with `-short` to skip them: `go test -short ./...`

---

### Performance

**When should I use goroutines?**

Use goroutines when you have tasks that can run concurrently — I/O operations, handling multiple network connections, parallel processing of independent data. Goroutines are cheap (~2KB initial stack) so you can create thousands. Don't use them for CPU-bound tasks that don't benefit from parallelism on a single core — goroutines aren't magic parallelism.

**How does Go manage memory?**

Go uses a concurrent, tri-color, mark-and-sweep garbage collector. You don't allocate or free memory manually. The GC runs concurrently with your program, pausing all goroutines only briefly (typically <1ms). Tune GC behavior with `GOGC` (default: 100, meaning GC runs when heap grows 100%) and `GOMEMLIMIT` (soft memory limit for the process).

```bash
GOGC=50 ./myapp     # More frequent GC, less memory
GOGC=200 ./myapp    # Less frequent GC, more memory, less CPU
GOMEMLIMIT=1GiB ./myapp  # Soft memory ceiling
```

**How do I profile a Go program?**

Three main approaches:

1. **Test benchmarks:** `go test -cpuprofile=cpu.prof -memprofile=mem.prof -bench=.`
2. **Runtime pprof:** `import _ "net/http/pprof"` then fetch profiles via HTTP
3. **Execution trace:** `go test -trace=trace.out` then `go tool trace trace.out`

Analyze profiles with: `go tool pprof -http=:8080 cpu.prof`

**What is PGO (profile-guided optimization)?**

PGO (Go 1.21+) uses CPU profiles from production runs to optimize the next build. Place a `default.pgo` file in your main package directory, and `go build` automatically applies optimizations — inlining hot functions, improving branch prediction, etc. Typical improvement: 2-7%.

---

### Tooling

**What's the difference between `gofmt` and `go fmt`?**

`gofmt` is the standalone formatting tool with additional flags (`-d` for diff, `-s` for simplification). `go fmt` is a convenience wrapper that runs `gofmt -l -w` on each `.go` file in a package. For most users, `go fmt ./...` is sufficient.

**What does `go vet` check for?**

`go vet` runs a suite of static analyzers that catch common mistakes:

- Printf format/argument mismatches
- Unreachable code
- Incorrect struct tags
- Suspicious mutex/lock copies
- Boolean expression simplification
- Unused results of certain functions
- Invalid build constraints
- Assembly/Go declaration mismatches

It has a deliberately low false-positive rate. Every finding should be investigated.

**How do I manage tool dependencies?**

Go 1.24 introduced tool dependencies. Add tools to your module:

```bash
go get -tool golang.org/x/tools/cmd/stringer
```

This records the tool in `go.mod` and ensures everyone on the team uses the same version. Run tools with:

```bash
go tool stringer -type=MyEnum
```

**How do I see the Go source code for a standard library function?**

```bash
go doc -src fmt.Println
```

Or browse the source at [cs.opensource.google/go/go](https://cs.opensource.google/go/go) or [github.com/golang/go](https://github.com/golang/go/tree/master/src).

**What is `go telemetry`?**

Go 1.23+ includes opt-in telemetry for the Go team to understand toolchain usage. It defaults to `local` (collected but not uploaded). Use `go telemetry off` to disable collection entirely, or `go telemetry on` to opt in to uploading anonymized data.

**How do I write a Go plugin?**

Go supports plugins on Linux and macOS (not Windows). Build a plugin:

```bash
go build -buildmode=plugin -o myplugin.so ./plugin/
```

Load it at runtime:

```go
p, _ := plugin.Open("myplugin.so")
sym, _ := p.Lookup("MyFunc")
myFunc := sym.(func() string)
fmt.Println(myFunc())
```

Plugins must be compiled with the exact same Go version and dependency versions as the host binary.

**How do I use `go:linkname`?**

`go:linkname` is a compiler directive that lets you access unexported functions from other packages. It requires `import "unsafe"`:

```go
import _ "unsafe"

//go:linkname someInternalFunc runtime.someInternalFunc
func someInternalFunc()
```

This is an unsupported escape hatch — internal APIs can change without notice. Avoid it in production code.

**How do I use `GOEXPERIMENT`?**

`GOEXPERIMENT` enables experimental features that aren't yet the default:

```bash
GOEXPERIMENT=rangefunc go build .
```

Available experiments change between Go versions. Check the release notes for what's available.

---

### Concurrency

**What's the difference between goroutines and OS threads?**

Goroutines are multiplexed onto a small number of OS threads by Go's runtime scheduler. A goroutine starts with ~2KB of stack (vs ~1MB for an OS thread) and grows dynamically. You can run millions of goroutines on a single machine. The runtime handles scheduling, preemption, and work-stealing across available CPU cores.

**How do channels work?**

Channels are typed conduits for communication between goroutines:

```go
ch := make(chan string)       // unbuffered
ch := make(chan string, 10)   // buffered (capacity 10)

go func() { ch <- "hello" }()  // send
msg := <-ch                     // receive
```

Unbuffered channels synchronize sender and receiver. Buffered channels allow sends to proceed until full. Use `select` for multiplexing multiple channels.

**When should I use `sync.Mutex` vs channels?**

Use `sync.Mutex` when protecting shared data from concurrent access (simple locking). Use channels when communicating between goroutines or when building pipelines. The Go proverb: "Don't communicate by sharing memory; share memory by communicating." In practice, mutexes are simpler for guarding a single data structure; channels are better for coordinating workflows.

**How do I wait for multiple goroutines to finish?**

Use `sync.WaitGroup`:

```go
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
    wg.Add(1)
    go func(id int) {
        defer wg.Done()
        process(id)
    }(i)
}
wg.Wait()
```

Or use `golang.org/x/sync/errgroup` for goroutine groups with error propagation.

**How do I limit concurrency?**

Use a semaphore pattern with a buffered channel:

```go
sem := make(chan struct{}, 10) // max 10 concurrent
for _, item := range items {
    sem <- struct{}{} // acquire
    go func(it Item) {
        defer func() { <-sem }() // release
        process(it)
    }(item)
}
```

Or use `golang.org/x/sync/semaphore` for a weighted semaphore.

---

### Deployment

**What's the recommended Dockerfile for Go?**

Use a multi-stage build for minimal images:

```dockerfile
FROM golang:1.24 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' -o /app/server .

FROM scratch
COPY --from=builder /app/server /server
ENTRYPOINT ["/server"]
```

The `scratch` base image produces the smallest possible container. Use `alpine` if you need a shell for debugging or CA certificates (`COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/`).

**How do I handle signals for graceful shutdown?**

```go
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()

server := &http.Server{Addr: ":8080"}
go func() {
    <-ctx.Done()
    server.Shutdown(context.Background())
}()
server.ListenAndServe()
```

**How do I compile for embedded Linux / IoT devices?**

Cross-compile with the appropriate `GOOS`, `GOARCH`, and `GOARM`:

```bash
GOOS=linux GOARCH=arm GOARM=6 CGO_ENABLED=0 go build -ldflags='-s -w' -o myapp .
```

Go supports ARM (v5, v6, v7), ARM64, MIPS, RISC-V, and other architectures commonly found in embedded devices.

---

_Generated May 2026 from golang/go at 1644917. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
