Jesse A. Green / notebook

Go — Administrator & Developer Guide

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.

1. Architecture Overview

Go is a statically typed, compiled programming language designed for simplicity, reliability, and efficiency at scale. The golang/go repository contains the entire Go toolchain: the gc compiler that produces native machine code, a sophisticated runtime providing goroutine scheduling and garbage collection, approximately 150 standard library packages, and the go CLI that orchestrates builds, testing, module management, and tooling. The system is entirely self-hosted — Go compiles itself.

The toolchain targets over 20 OS/architecture combinations from a single source tree. Cross-compilation requires no additional toolchains: setting GOOS and GOARCH environment variables before go build produces a native binary for the target platform. The compiler uses an SSA-based intermediate representation with platform-specific code generators, and the linker produces statically linked binaries by default (though dynamic linking, shared libraries, and plugin modes are supported).

The runtime is the invisible backbone of every Go program. It implements an M:N goroutine scheduler that multiplexes potentially millions of goroutines onto a smaller pool of OS threads, a concurrent tri-color mark-sweep garbage collector with sub-millisecond pause times, a hierarchical memory allocator (mcache → mcentral → mheap), growable stacks, channel operations, netpoller-based I/O multiplexing, and the reflection/type system. The runtime is written in a mix of Go and platform-specific assembly.

Source Code (.go files)
    │
    ▼
┌─────────────┐
│  go command  │  (src/cmd/go) — build orchestration, module mgmt
└─────┬───────┘
      │
      ▼
┌─────────────┐    ┌──────────┐    ┌──────────┐
│   compile    │───▶│   link   │───▶│ binary   │
│ (src/cmd/    │    │(src/cmd/ │    │ output   │
│  compile)    │    │  link)   │    └──────────┘
└─────────────┘    └──────────┘
      │
┌─────┴──────────────────────┐
│ Supporting Tools           │
│ asm, cgo, vet, cover,      │
│ trace, pprof, fix, objdump │
└────────────────────────────┘

Runtime (src/runtime):
┌────────────────────────────────────┐
│ Goroutine Scheduler (M:N)          │
│ Garbage Collector (concurrent,     │
│   tri-color mark-sweep)            │
│ Memory Allocator (mcache/mcentral/ │
│   mheap, spans)                    │
│ System Calls / OS Interface        │
│ Stack Management (growable stacks) │
│ Channel Operations                 │
│ Reflection / Type System           │
└────────────────────────────────────┘

Standard Library (~150 packages in src/):
  bufio, bytes, compress, container, context, crypto, database,
  debug, embed, encoding, errors, expvar, flag, fmt, go (ast/parser/
  types/doc), hash, html, image, io, iter, log, maps, math, mime,
  net (http, rpc), os, path, plugin, reflect, regexp, runtime,
  slices, sort, strconv, strings, structs, sync, syscall, testing,
  text, time, unicode, unique, unsafe, weak, cmp, arena, simd

Note

Go is self-hosted: the compiler, linker, assembler, and all tools are written in Go. Building Go from source requires a pre-existing Go installation (Go 1.22.6 or later) as a bootstrap toolchain, set via the GOROOT_BOOTSTRAP environment variable.

Component Inventory

Component Path Role
go command src/cmd/go/ Build orchestration, module management, test runner, code generation, dependency resolution
Compiler (gc) src/cmd/compile/ Compiles Go source → native machine code via SSA pipeline
Linker src/cmd/link/ Links object files + runtime into executables, shared libs, or archives
Assembler src/cmd/asm/ Assembles Go assembly (.s files) using Plan 9-derived syntax
cgo src/cmd/cgo/ C/Go interop bridge — generates Go and C stubs for cross-language calls
vet src/cmd/vet/ Static analysis: printf format strings, struct tags, unreachable code, etc.
trace src/cmd/trace/ Execution tracer viewer — HTTP UI for goroutine/scheduler/network analysis
cover src/cmd/cover/ Code coverage instrumentation and reporting
pprof src/cmd/pprof/ CPU/memory/block profiling tool (wraps google/pprof)
objdump src/cmd/objdump/ Disassembles Go binaries
addr2line src/cmd/addr2line/ Translates program addresses to source file:line
test2json src/cmd/test2json/ Converts test output to machine-readable JSON
preprofile src/cmd/preprofile/ Preprocesses CPU profiles for profile-guided optimization (PGO)
fix src/cmd/fix/ Automatically updates Go source for API changes between releases
api src/cmd/api/ Checks API compatibility — enforces the Go 1 compatibility promise
covdata src/cmd/covdata/ Merges and reports on coverage data files
pack src/cmd/pack/ Creates and manipulates Go archive files
Runtime src/runtime/ Scheduler, GC, memory allocator, stacks, channels (594 files, 4.7M chars)
Standard Library src/ (various) ~150 packages covering I/O, networking, crypto, encoding, testing, etc.

Technology Stack

Technology Version / Detail
Language Go (self-hosted since Go 1.5, 2015)
Build system Self-bootstrapping via make.bash / all.bash / make.bat
Module system Go modules (go.mod, go.sum) — default since Go 1.16
Go version 1.27 (per go.mod)
Standard dependencies golang.org/x/crypto, x/net, x/sys, x/text
Tool dependencies golang.org/x/tools, x/mod, x/arch, x/build, x/sync, x/telemetry, x/term
Supported OS Linux, macOS, Windows, FreeBSD, OpenBSD, NetBSD, DragonFly, Plan 9, AIX, Solaris, Illumos, iOS, Android, WASM (js, wasip1)
Supported architectures amd64, arm64, 386, arm, ppc64/ppc64le, mips/mipsle, mips64/mips64le, riscv64, s390x, loong64, wasm

Data Flow: go build

The build pipeline proceeds through these stages:

  1. Package resolution — the go command resolves import paths, reads go.mod and go.sum, downloads missing modules from the module proxy (GOPROXY), and constructs the dependency graph.
  2. Build graph construction — the go command determines which packages need compilation based on source modification times and the build cache (GOCACHE).
  3. Compilation — for each package, compile parses source into AST, type-checks, constructs IR, performs inlining and escape analysis, generates SSA, runs optimization passes, and emits machine code as an object file.
  4. Linking — link combines all object files with the runtime package into a single executable. It resolves symbols, lays out sections, writes DWARF debug info, and produces the final binary in the target format (ELF, Mach-O, PE, or Plan 9 a.out).
.go source → parse → type-check → IR → inline/escape → SSA → optimize → codegen → .o
                                                                                    │
                                                                                    ▼
                                                              link (.o + runtime → executable)

2. System Requirements

Building Go from Source

Building Go from source requires a bootstrap Go toolchain. The bootstrap version requirement increases with each release.

Requirement Detail
Bootstrap toolchain Go 1.22.6 or later (set GOROOT_BOOTSTRAP to its root)
Disk space ~2.5 GB for the source tree + build artifacts
RAM 4 GB minimum for building; 8 GB+ recommended for running all tests
Build time 2–10 minutes depending on hardware (just build); 15–45 minutes with all tests (all.bash)
Git Required for git clone and for build metadata embedding
C compiler Required only if CGO_ENABLED=1 (default on native builds); GCC or Clang

Supported Platforms

Go classifies platform support into tiers:

First class (full support, tested in CI, release binaries provided):

  • linux/amd64, linux/arm64, linux/386
  • darwin/amd64, darwin/arm64
  • windows/amd64, windows/arm64
  • freebsd/amd64

Second class (tested in CI, most issues fixed):

  • linux/arm, linux/ppc64le, linux/s390x, linux/riscv64, linux/loong64
  • freebsd/386, freebsd/arm64
  • openbsd/amd64
  • netbsd/amd64
  • windows/386

Third class (code present, not actively tested):

  • aix/ppc64, dragonfly/amd64, illumos/amd64, solaris/amd64
  • plan9/386, plan9/amd64, plan9/arm
  • js/wasm, wasip1/wasm
  • Various other OS/arch combinations

Bootstrap Process

# Clone the repository
git clone https://go.googlesource.com/go
cd go/src

# Set bootstrap toolchain (must be Go 1.22.6+)
export GOROOT_BOOTSTRAP=/usr/local/go1.22

# Build only (fast)
./make.bash

# Build + run all tests (thorough)
./all.bash

On Windows, use make.bat and all.bat instead. The built toolchain appears in ../bin/go.

Important

The bootstrap toolchain version is a hard requirement. Attempting to build with an older Go version produces a clear error message during make.bash. If you do not have a sufficiently recent Go installation, download a binary release from https://go.dev/dl/ to use as the bootstrap.

Cross-Compilation Requirements

Cross-compilation requires no additional tools for pure Go code:

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

For cgo cross-compilation, a C cross-compiler targeting the destination platform is required, and CGO_ENABLED=1 must be set explicitly (it defaults to 0 for cross-compilation).


3. Configuration Reference

Go's behavior is controlled through environment variables, build flags, module files (go.mod, go.work), and build constraints. All persistent environment variable settings are managed through go env -w and stored in the user's environment file (default: $HOME/.config/go/env, or the path in $GOENV).

3.1 General-Purpose Environment Variables

Variable Description Default go env -w
GO111MODULE Module mode: on, off, or auto "" (same as on) Yes
GOARCH Target architecture for compilation Host architecture Yes
GOAUTH Authentication for module fetches (space-separated netrc|command directives) netrc Yes
GOBIN Directory for installed binaries (go install) $GOPATH/bin Yes
GOCACHE Build cache directory OS-specific default (~/.cache/go-build on Linux) Yes
GOCACHEPROG External program for build cache storage "" Yes
GODEBUG Comma-separated runtime debug settings "" No
GOENV Path to the Go environment config file $HOME/.config/go/env No
GOFLAGS Default flags applied to all go commands "" Yes
GOINSECURE Glob patterns of modules fetched without TLS or checksum verification "" Yes
GOMODCACHE Module download cache directory $GOPATH/pkg/mod Yes
GOOS Target operating system for compilation Host OS Yes
GOPATH Workspace root (legacy; modules reduce its role) $HOME/go Yes
GOPRIVATE Glob patterns for private modules (sets both GONOPROXY and GONOSUMDB) "" Yes
GONOPROXY Glob patterns of modules fetched directly, not via proxy GOPRIVATE Yes
GONOSUMDB Glob patterns of modules not verified against checksum database GOPRIVATE Yes
GOPROXY Module proxy URLs (comma or pipe separated) https://proxy.golang.org,direct Yes
GOROOT Root of the Go installation Inferred from go binary location No
GOSUMDB Checksum database name, URL, and public key sum.golang.org Yes
GOTMPDIR Directory for temporary files "" (system default) Yes
GOTOOLCHAIN Toolchain selection: local, auto, or specific version "" Yes
GOVCS Allowed VCS tools per module pattern public:git|hg,private:all Yes
GOWORK Path to go.work file, or off to disable Auto-detected Yes
GCCGO gccgo compiler command gccgo Yes

Note

GODEBUG and GOENV cannot be set with go env -w. GODEBUG is set per-binary via the //go:debug directive in package main or in go.mod via the godebug directive. The GOENV variable controls where go env -w writes, so it must be set in the OS environment.

3.2 Cgo Environment Variables

These control C/C++/Fortran compilation when cgo is enabled.

Variable Description Default
CGO_ENABLED Enable/disable cgo 1 for native builds, 0 for cross-compilation
CC C compiler command cc or gcc
CXX C++ compiler command c++ or g++
FC Fortran compiler command gfortran
AR Archive tool ar
PKG_CONFIG pkg-config tool pkg-config
CGO_CFLAGS Flags for C compiler ""
CGO_CPPFLAGS Flags for C preprocessor ""
CGO_CXXFLAGS Flags for C++ compiler ""
CGO_FFLAGS Flags for Fortran compiler ""
CGO_LDFLAGS Flags for linker (when using cgo) ""

Each CGO_*FLAGS variable has corresponding _ALLOW and _DISALLOW variants that take regular expressions to control which flags are permitted. These exist for security: preventing malicious packages from injecting dangerous compiler/linker flags.

Variable Purpose
CGO_CFLAGS_ALLOW Regex of allowed additional C flags
CGO_CFLAGS_DISALLOW Regex of disallowed C flags
CGO_CPPFLAGS_ALLOW / _DISALLOW Same for preprocessor
CGO_CXXFLAGS_ALLOW / _DISALLOW Same for C++
CGO_FFLAGS_ALLOW / _DISALLOW Same for Fortran
CGO_LDFLAGS_ALLOW / _DISALLOW Same for linker

3.3 Architecture-Specific Variables

These control instruction set extensions and ABI details for specific architectures.

Variable Values Default Description
GO386 sse2, softfloat sse2 x86 floating point implementation
GOAMD64 v1, v2, v3, v4 v1 AMD64 microarchitecture level (v1=baseline, v2=CMPXCHG16B/POPCNT/SSE4.2, v3=AVX2/BMI2/FMA, v4=AVX-512)
GOARM 5, 6, 7 7 (most systems) ARM version (5=no VFP, 6=VFPv1, 7=VFPv3)
GOARM64 v8.{0-9}, with optional ,lse and ,crypto v8.0 ARM64 architecture version and extensions
GOMIPS hardfloat, softfloat hardfloat MIPS floating point
GOMIPS64 hardfloat, softfloat hardfloat MIPS64 floating point
GOPPC64 power8, power9, power10 power8 PowerPC 64-bit ISA level
GORISCV64 rva20u64, rva22u64 rva20u64 RISC-V 64-bit profile
GOWASM comma-separated: satconv, signext "" WebAssembly feature flags

3.4 Special-Purpose Variables

Variable Description
GOCOVERDIR Directory for coverage data files written by coverage-instrumented binaries
GOEXPERIMENT Comma-separated experimental feature flags
GOFIPS140 FIPS 140 compliance mode and version (off, latest, or specific version)
GO_EXTLINK_ENABLED Force external linking on/off (0 or 1)
GIT_ALLOW_PROTOCOL Allowed Git protocols (colon-separated)
GCCGOTOOLDIR Directory containing gccgo tools

3.5 Read-Only Variables (from go env)

These are informational and cannot be set by the user:

Variable Description
GOEXE Executable file suffix (.exe on Windows, empty elsewhere)
GOGCCFLAGS Flags supplied to the C compiler by go build
GOHOSTARCH Architecture of the host (the machine running go)
GOHOSTOS OS of the host
GOMOD Path to the go.mod of the main module
GOTELEMETRY Telemetry upload mode (off, local, on)
GOTELEMETRYDIR Directory for telemetry data
GOTOOLDIR Directory containing Go tool binaries
GOVERSION Go version string (e.g., go1.27)

3.6 Build Flags

These flags are shared across go build, go clean, go get, go install, go list, go run, and go test:

Flag Description
-C dir Change to dir before executing
-a Force rebuild of all packages
-n Print commands without executing
-p n Number of parallel builds (default: GOMAXPROCS)
-race Enable race detector
-msan Enable memory sanitizer (C/C++ via Clang)
-asan Enable address sanitizer (C/C++ via Clang/GCC)
-cover Enable code coverage instrumentation
-covermode mode Coverage mode: set, count, or atomic
-coverpkg pattern Apply coverage to matching packages
-v Verbose: print package names as compiled
-work Print and preserve the temporary work directory
-x Print commands as executed
-asmflags '[pattern=]flags' Flags for go tool asm
-buildmode mode Build mode (see below)
-buildvcs Embed version control info (true, false, auto)
-compiler name Compiler to use: gc or gccgo
-gccgoflags flags Flags for gccgo compiler/linker
-gcflags '[pattern=]flags' Flags for go tool compile
-installsuffix suffix Suffix for the install directory (to separate outputs)
-json Output build events as JSON
-ldflags '[pattern=]flags' Flags for go tool link
-linkshared Build for linking against shared libraries
-mod mode Module download mode: readonly, vendor, or mod
-modcacherw Leave module cache directories read-write
-modfile file Use an alternate go.mod file
-overlay file JSON file mapping actual→replacement source files
-pgo file Profile-guided optimization profile (or auto for default.pgo)
-pkgdir dir Install/load packages from dir instead of default
-tags tags Comma-separated build tags
-trimpath Remove file system paths from the binary
-toolexec cmd Prefix tool invocations with cmd

3.7 Build Modes

Mode -buildmode= Output
default (default) Regular executable
archive archive Non-main packages → .a archive files
c-archive c-archive Main package → C-callable static archive (.a + header)
c-shared c-shared Main package → C-callable shared library (.so / .dylib)
shared shared Non-main packages → shared library for -linkshared
exe exe Executable (same as default, explicit)
pie pie Position-independent executable
plugin plugin Go plugin (.so), loadable at runtime via plugin package

3.8 go.mod Directives

The go.mod file defines a module's properties and dependencies.

Directive Syntax Purpose
module module example.com/mymod Declares the module path
go go 1.27 Minimum Go version required
toolchain toolchain go1.27.0 Preferred toolchain version
godebug godebug setting=value Default GODEBUG settings for binaries in this module
require require example.com/dep v1.2.3 Declares a dependency
exclude exclude example.com/dep v1.0.0 Excludes a specific module version
replace replace old => new v1.0.0 Replaces a module (or version) with another
retract retract v1.0.0 Marks a version of this module as retracted
tool tool example.com/tool Declares a tool dependency
ignore ignore example.com/dir Ignores a subdirectory

3.9 go.work Directives

The go.work file defines a workspace for multi-module development.

Directive Syntax Purpose
go go 1.27 Go version for the workspace
toolchain toolchain go1.27.0 Preferred toolchain
godebug godebug setting=value Debug settings for the workspace
use use ./mymod Adds a local module to the workspace
replace replace old => new Module replacement (workspace-wide)

3.10 Build Constraints

Build constraints control which files are included in a build. The modern syntax uses //go:build lines (Go 1.17+):

//go:build linux && amd64

package mypackage

Available constraint tags:

Category Tags
Operating system linux, darwin, windows, freebsd, openbsd, netbsd, dragonfly, solaris, illumos, aix, plan9, js, wasip1, ios, android
Architecture amd64, arm64, 386, arm, ppc64, ppc64le, mips, mipsle, mips64, mips64le, riscv64, s390x, loong64, wasm
Special cgo (cgo enabled), unix (any Unix-like OS), boringcrypto, goexperiment.X
Go version go1.21 (true if Go version >= 1.21)
Custom Any tag passed via -tags
Ignore ignore (never builds)

File naming conventions also serve as implicit constraints: *_linux.go, *_amd64.go, *_linux_amd64.go, and *_test.go files are automatically constrained.

Important

The //go:build line must appear before the package clause and be followed by a blank line. The older // +build syntax is still accepted but the go fmt tool automatically adds the equivalent //go:build line. New code should use only //go:build.


4. Deployment & Scaling

4.1 Building Go from Source

For production environments requiring a custom Go toolchain (patched, custom experiments, FIPS builds), building from source is the standard approach.

# Prerequisites: Git, a bootstrap Go (1.22.6+), C compiler (optional, for cgo)
git clone https://go.googlesource.com/go $HOME/go-src
cd $HOME/go-src
git checkout go1.27.0  # or desired release tag

# Set bootstrap
export GOROOT_BOOTSTRAP=/usr/local/go

# Build (fast, no tests)
cd src
./make.bash

# The new toolchain is at $HOME/go-src/bin/go
export PATH=$HOME/go-src/bin:$PATH
go version

For a verified build with all tests:

cd $HOME/go-src/src
./all.bash   # Runs make.bash + comprehensive test suite

Tip

On CI systems, use make.bash for speed and run selective tests separately. The full all.bash takes 15–45 minutes and tests every standard library package including slow network and race detector tests.

4.2 Cross-Compilation

Go's cross-compilation is a first-class feature requiring zero additional toolchains for pure Go:

# Linux ARM64 from any host
GOOS=linux GOARCH=arm64 go build -o server-arm64 ./cmd/server

# Windows from Linux/macOS
GOOS=windows GOARCH=amd64 go build -o server.exe ./cmd/server

# macOS universal binary (build both, then lipo)
GOOS=darwin GOARCH=amd64 go build -o server-amd64 ./cmd/server
GOOS=darwin GOARCH=arm64 go build -o server-arm64 ./cmd/server
lipo -create -output server server-amd64 server-arm64

# WebAssembly
GOOS=js GOARCH=wasm go build -o main.wasm ./cmd/wasm-app
# Or WASI
GOOS=wasip1 GOARCH=wasm go build -o main.wasm ./cmd/wasm-app

For cgo cross-compilation, provide the target C compiler:

CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc \
  GOOS=linux GOARCH=arm64 \
  go build -o server-arm64 ./cmd/server

4.3 Build Modes for Libraries

C-archive — produce a static library callable from C:

# main.go must have //export directives and a main() function
go build -buildmode=c-archive -o libfoo.a ./cmd/cfoo
# Produces libfoo.a and libfoo.h

C-shared — produce a shared library callable from C:

go build -buildmode=c-shared -o libfoo.so ./cmd/cfoo
# Produces libfoo.so and libfoo.h

Plugin — produce a Go plugin loadable at runtime:

go build -buildmode=plugin -o myplugin.so ./plugins/myplugin
// Loading a plugin at runtime
p, err := plugin.Open("myplugin.so")
sym, err := p.Lookup("Handler")
handler := sym.(func(string) string)

PIE — position-independent executable (required by some security policies):

go build -buildmode=pie -o server ./cmd/server

4.4 Reproducible Builds

For reproducible, hermetic builds:

go build -trimpath -buildvcs=false -ldflags="-s -w" -o server ./cmd/server
Flag Effect
-trimpath Removes all local file paths from the binary (GOPATH, GOROOT, module paths)
-buildvcs=false Omits VCS info (commit hash, modified status) from the binary
-ldflags="-s -w" Strips symbol table and DWARF debug info (smaller binary)

4.5 Module Proxy Configuration

For organizations running a private module proxy or using Athens/GOPROXY:

# Use a corporate proxy with fallback to direct
go env -w GOPROXY=https://goproxy.corp.example.com,https://proxy.golang.org,direct

# Private modules bypass proxy and checksum DB
go env -w GOPRIVATE=*.corp.example.com,github.com/myorg/*

# Or set independently
go env -w GONOPROXY=*.corp.example.com
go env -w GONOSUMDB=*.corp.example.com

# Authentication for private repos
go env -w GOAUTH="netrc"
# Requires ~/.netrc with credentials:
# machine github.com login TOKEN password x-oauth-basic

The proxy protocol is HTTP-based. A proxy serves these paths:

Path Returns
$base/$module/@v/list Newline-separated list of known versions
$base/$module/@v/$version.info JSON with version and time
$base/$module/@v/$version.mod go.mod for that version
$base/$module/@v/$version.zip Source zip for that version
$base/$module/@latest JSON for the latest version

4.6 Toolchain Management

Go 1.21+ supports automatic toolchain downloads based on go and toolchain directives in go.mod:

# Use the latest patch of Go 1.27
go env -w GOTOOLCHAIN=auto

# Pin to a specific toolchain
go env -w GOTOOLCHAIN=go1.27.0

# Only use the locally installed Go
go env -w GOTOOLCHAIN=local

# Upgrade the go directive in go.mod
go get go@1.27
go get toolchain@go1.27.0

When GOTOOLCHAIN=auto and a module requires a newer Go version than the local installation, the go command automatically downloads and switches to the required version.

Tip

In CI/CD pipelines, setting GOTOOLCHAIN=local prevents unexpected toolchain downloads and ensures builds use exactly the Go version you installed. For development, auto provides a seamless experience.

4.7 Vendor Mode

For air-gapped or highly controlled deployments:

# Vendor all dependencies into ./vendor/
go mod vendor

# Build from vendor (automatic if vendor/ exists, or explicit)
go build -mod=vendor ./...

# Verify vendor directory matches go.sum
go mod verify

4.8 Container and Docker Deployments

Go's static binary compilation makes it ideal for minimal container images.

Multi-stage Dockerfile (recommended):

# Build stage
FROM golang:1.27 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
    go build -trimpath -ldflags="-s -w" -o /server ./cmd/server

# Runtime stage — scratch (zero-dependency)
FROM scratch
COPY --from=builder /server /server
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
EXPOSE 8080
ENTRYPOINT ["/server"]

Key considerations for containerized Go:

Concern Solution
Image size Use scratch or distroless base; CGO_ENABLED=0 for static linking
TLS certificates Copy /etc/ssl/certs/ca-certificates.crt from builder or use distroless
Timezone data Import _ "time/tzdata" to embed in binary, or copy zoneinfo.zip
DNS resolution CGO_ENABLED=0 uses pure Go resolver (no libc dependency)
Memory limits Set GOMEMLIMIT to ~90% of container memory limit
Signal handling Go handles SIGTERM properly; use context.Context for graceful shutdown
Health checks Implement /healthz or /readyz endpoints
UID/GID Use USER nonroot:nonroot with distroless, or create a user in Alpine

Alpine-based image (when cgo is needed):

FROM golang:1.27-alpine AS builder
RUN apk add --no-cache gcc musl-dev
WORKDIR /app
COPY . .
RUN go build -ldflags="-s -w" -o /server ./cmd/server

FROM alpine:3.21
RUN apk add --no-cache ca-certificates tzdata
COPY --from=builder /server /server
USER nobody:nobody
ENTRYPOINT ["/server"]

Distroless image (Google's minimal runtime):

FROM golang:1.27 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /server ./cmd/server

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /server /server
ENTRYPOINT ["/server"]

Tip

For production containers, always set GOMEMLIMIT via an environment variable in your deployment manifest. Without it, the Go runtime has no awareness of container memory limits and may consume more memory than the container allows, triggering OOM kills. A good rule of thumb: GOMEMLIMIT = 90% of the container's memory limit.

4.9 Ldflags: Injecting Build Information

The -ldflags flag passes options to the Go linker. Common uses:

# Inject version information at build time
go build -ldflags="-X 'main.Version=1.2.3' -X 'main.Commit=$(git rev-parse HEAD)' -X 'main.BuildTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)'" ./cmd/server
package main

var (
    Version   = "dev"
    Commit    = "unknown"
    BuildTime = "unknown"
)

Common linker flags:

Flag Effect
-s Omit the symbol table (smaller binary)
-w Omit DWARF debug information (smaller binary)
-X importpath.name=value Set a string variable at link time
-extldflags flags Pass flags to the external linker
-linkmode external Force external linking (use system linker)
-linkmode internal Force internal linking (Go's own linker)
-buildid=value Set the build ID (use "" for reproducible builds)
-H type Set executable format header type

Static linking with external dependencies:

# Fully static binary with musl (for Alpine/scratch)
CGO_ENABLED=1 go build -ldflags='-extldflags "-static"' -o server ./cmd/server

# With static linking and stripped symbols
CGO_ENABLED=1 go build -ldflags='-s -w -extldflags "-static"' -o server ./cmd/server

5. Operations

5.1 Build Cache Management

The build cache (GOCACHE) stores compiled package objects and test results. It dramatically speeds up incremental builds.

# View cache location
go env GOCACHE
# Typically: ~/.cache/go-build (Linux), ~/Library/Caches/go-build (macOS),
#            %LocalAppData%\go-build (Windows)

# Clear entire build cache
go clean -cache

# Clear build + test cache
go clean -testcache

# View cache statistics
ls -la $(go env GOCACHE) | head -20

Tip

The build cache grows unboundedly. On CI systems, periodically run go clean -cache or set GOCACHE to a directory cleaned by your CI cache policy. For local development, the cache rarely causes disk pressure problems — it typically stays under 1 GB.

GODEBUG cache diagnostics:

Setting Effect
GODEBUG=gocacheverify=1 Verifies every cache hit by rebuilding and comparing
GODEBUG=gocachehash=1 Logs cache hash computations for debugging cache misses
GODEBUG=gocachetest=1 Logs test cache lookup details
# Debug why a package keeps rebuilding
GODEBUG=gocachehash=1 go build -v ./pkg/mypackage 2>&1 | grep cache

5.2 Test Cache

Test results are cached when the test binary and all its inputs are unchanged. Cached test results display (cached) instead of a duration.

Flags that preserve cacheability (these are included in the cache key):

-benchtime, -cpu, -failfast, -fullpath, -list, -parallel, -run, -short, -skip, -timeout, -v

Actions that bypass the test cache:

# Force tests to re-run (most common)
go test -count=1 ./...

# Clear only test results from cache
go clean -testcache

# Explicit cache-busting flag
go test -run TestSpecific -count=1 ./pkg/...

Note

Test caching only applies to successful tests. Failing tests are always re-run. Tests that read files, environment variables, or network resources outside the test binary's own package may show stale cached results — use -count=1 in those cases.

5.3 Module Cache

The module cache (GOMODCACHE, default $GOPATH/pkg/mod) stores downloaded module sources. Unlike the build cache, module directories are read-only by default.

# View module cache location and size
go env GOMODCACHE
du -sh $(go env GOMODCACHE)

# Remove entire module cache (requires confirmation)
go clean -modcache

# Make module cache directories read-write (for cleanup scripts)
go build -modcacherw ./...

# Verify module downloads match go.sum
go mod verify

5.4 Fuzz Cache

The fuzzing engine caches interesting inputs (corpus entries) that expand coverage.

# View fuzz cache location (inside GOCACHE)
ls $(go env GOCACHE)/fuzz/

# Clear only fuzz cache
go clean -fuzzcache

5.5 Telemetry Management

Go collects anonymous usage and crash telemetry (since Go 1.23). It is opt-in for uploading.

# Check current telemetry mode
go telemetry

# Disable all telemetry collection
go telemetry off

# Collect locally but don't upload
go telemetry local

# Opt in to uploading
go telemetry on

# View telemetry data directory
go env GOTELEMETRYDIR

Note

Telemetry data collected in local mode is stored on disk but never transmitted. Setting go telemetry off prevents even local data collection. In corporate environments, off is the conservative choice. The telemetry system is documented at https://telemetry.go.dev/.

5.6 Test Flags Reference

The go test command accepts all build flags plus test-specific flags:

Test binary flags (passed before the package list):

Flag Description Default
-bench regexp Run benchmarks matching regexp None (no benchmarks run)
-benchtime t Run each benchmark for duration t or N iterations (100x) 1s
-benchmem Report memory allocations in benchmark results false
-count n Run tests/benchmarks n times 1
-cover Enable coverage analysis false
-covermode mode Coverage mode: set, count, or atomic set (atomic with -race)
-coverprofile file Write coverage profile to file None
-coverpkg pattern Measure coverage for matching packages Package under test only
-cpu list Comma-separated GOMAXPROCS values to test with Current GOMAXPROCS
-failfast Stop after first test failure false
-fullpath Show full file paths in error messages false
-fuzz regexp Run the fuzz test matching regexp None
-fuzztime t Run fuzzing for duration t or N iterations Indefinite (Ctrl+C to stop)
-fuzzminimizetime t Minimize fuzzing corpus for duration t 60s
-json Output test results as JSON (one event per line) false
-list regexp List tests/benchmarks/fuzz/examples matching regexp None
-outputdir dir Write profiles and coverage to dir Test binary directory
-parallel n Allow n tests to run in parallel via t.Parallel() GOMAXPROCS
-run regexp Run tests matching regexp All tests
-short Enable short mode (tests call testing.Short()) false
-shuffle off|on|N Randomize test execution order off
-skip regexp Skip tests matching regexp None
-timeout d Panic if a test binary runs longer than d 10m
-v Verbose output (print test names and t.Log output) false

Coverage workflow:

# Generate coverage profile
go test -coverprofile=coverage.out ./...

# View per-function coverage
go tool cover -func=coverage.out

# View annotated HTML report
go tool cover -html=coverage.out -o coverage.html

# Measure coverage across multiple packages
go test -coverpkg=./... -coverprofile=coverage.out ./...

# Coverage-instrumented binary (runs in production to collect coverage)
go build -cover -o server ./cmd/server
GOCOVERDIR=/tmp/coverdata ./server
# After shutdown:
go tool covdata textfmt -i=/tmp/coverdata -o=coverage.out

Benchmark workflow:

# Run benchmarks
go test -bench=. -benchmem ./pkg/server

# Run specific benchmark with multiple GOMAXPROCS values
go test -bench=BenchmarkHandle -cpu=1,2,4,8 -benchmem ./pkg/server

# Run benchmark for a specific duration
go test -bench=BenchmarkHandle -benchtime=10s ./pkg/server

# Run benchmark N times (for benchstat)
go test -bench=. -count=10 -benchmem ./pkg/server > bench.txt

# Memory profile during benchmarks
go test -bench=BenchmarkHandle -memprofile=mem.pprof ./pkg/server

# CPU profile during benchmarks
go test -bench=BenchmarkHandle -cpuprofile=cpu.pprof ./pkg/server

# Block profile (lock contention)
go test -bench=BenchmarkHandle -blockprofile=block.pprof ./pkg/server

# Mutex profile
go test -bench=BenchmarkHandle -mutexprofile=mutex.pprof ./pkg/server

5.7 The go Command Operations Reference

Key operational subcommands:

Command Purpose
go build Compile packages and dependencies
go install Compile and install to $GOBIN
go run Compile and run a program
go test Run tests and benchmarks
go test -fuzz Run fuzz tests
go test -bench Run benchmarks
go test -cover Run with coverage
go vet Static analysis
go fmt / gofmt Format source code
go mod init Initialize a new module
go mod tidy Add missing / remove unused dependencies
go mod download Download dependencies to cache
go mod vendor Vendor dependencies
go mod verify Verify dependency integrity
go mod graph Print dependency graph
go mod why Explain why a package is needed
go mod edit Programmatically edit go.mod
go work init Initialize a workspace
go work use Add modules to workspace
go work sync Sync workspace dependencies
go get Update dependencies in go.mod
go list List packages or modules
go doc Show documentation
go generate Run code generation directives
go clean Remove build artifacts and caches
go env View/set environment
go version Print Go version
go tool Run a Go tool directly
go fix Apply API migrations
go telemetry Manage telemetry

5.7 Execution Trace Viewer

The go tool trace command launches an HTTP server for analyzing execution traces.

# Capture a trace
go test -trace=trace.out ./pkg/mypackage

# View the trace
go tool trace trace.out
# Opens HTTP server, typically at http://127.0.0.1:PORT

HTTP routes served by the trace viewer:

Route Content
/ Main page with links to all views
/trace Interactive trace viewer (Perfetto UI)
/jsontrace Raw trace data in JSON format
/static/ Static assets for the UI
/goroutines Goroutine analysis (grouped by function)
/goroutine?id=N Individual goroutine timeline
/mmu Minimum mutator utilization (GC impact)
/io I/O blocking profile
/block Synchronization blocking profile
/syscall System call blocking profile
/sched Scheduler latency profile
/regionio Region-scoped I/O profile
/regionblock Region-scoped blocking profile
/regionsyscall Region-scoped syscall profile
/regionsched Region-scoped scheduler profile
/userregions User-defined region summary
/userregion?region=NAME Individual user region
/usertasks User-defined task summary
/usertask?taskid=N Individual user task

5.8 Runtime Metrics and Monitoring

The expvar package exposes runtime metrics at a JSON endpoint:

import (
    "expvar"
    "net/http"
    _ "net/http/pprof"  // Register pprof handlers
)

func main() {
    // GET /debug/vars returns JSON with:
    //   "cmdline": os.Args
    //   "memstats": runtime.MemStats
    //   + any custom published variables
    http.ListenAndServe(":8080", nil)
}

GET /debug/vars returns a JSON object with cmdline (process arguments) and memstats (full runtime.MemStats snapshot), plus any variables registered with expvar.Publish().

5.9 Profiling Endpoints

The net/http/pprof package registers profiling handlers on the default mux:

Endpoint Profile
/debug/pprof/ Index page with links to all profiles
/debug/pprof/profile CPU profile (?seconds=30)
/debug/pprof/heap Heap memory allocations
/debug/pprof/goroutine All goroutine stacks
/debug/pprof/allocs Past memory allocations
/debug/pprof/block Blocking synchronization
/debug/pprof/mutex Contended mutex holders
/debug/pprof/threadcreate OS thread creation
/debug/pprof/trace Execution trace (?seconds=5)
/debug/pprof/cmdline Process command line
/debug/pprof/symbol Symbol lookup
# Capture and analyze a CPU profile from a running server
go tool pprof http://localhost:8080/debug/pprof/profile?seconds=30

# Capture a heap profile
go tool pprof http://localhost:8080/debug/pprof/heap

# Interactive pprof commands
(pprof) top 20
(pprof) web        # Opens graph in browser
(pprof) list main  # Show annotated source

6. Performance

6.1 Profile-Guided Optimization (PGO)

PGO uses CPU profiles from production workloads to guide compiler optimizations, typically yielding 2–7% throughput improvements.

# Step 1: Collect a CPU profile from production (or a representative benchmark)
go test -bench=. -cpuprofile=cpu.pprof ./...
# Or from a running server:
curl -o cpu.pprof 'http://localhost:8080/debug/pprof/profile?seconds=60'

# Step 2: Place the profile in the main package directory
cp cpu.pprof cmd/server/default.pgo

# Step 3: Build with PGO (auto-detects default.pgo)
cd cmd/server
go build -pgo=auto  # This is the default since Go 1.22

# Or specify an explicit profile
go build -pgo=/path/to/cpu.pprof

PGO optimizations include:

  • Devirtualization — interface method calls inlined when the profile shows a dominant concrete type
  • Inlining budget increases — hot functions get higher inlining budgets
  • Stenciling — generic function specialization for hot type parameters

Tip

PGO is safe to use in production. The worst case is no improvement. Place default.pgo in your module's main package directory and commit it to version control. Re-collect profiles periodically (e.g., monthly) to keep optimizations aligned with actual workload patterns.

6.2 Compiler Optimization Flags

The gc compiler accepts optimization-related flags via -gcflags:

# Disable optimizations (for debugging)
go build -gcflags="-N -l" ./...

# Print optimization decisions
go build -gcflags="-m" ./...        # Escape analysis + inlining decisions
go build -gcflags="-m -m" ./...     # Verbose (more detail)

# Print SSA for a specific function
GOSSAFUNC=main.handleRequest go build ./cmd/server
# Produces ssa.html in the current directory
Flag Effect
-N Disable optimizations
-l Disable inlining
-m Print optimization decisions
-S Print generated assembly
-B Disable bounds checking
-C Disable check of provably nil pointers
-d=ssa/check/on Enable SSA checks
-W Debug type checking

6.3 AMD64 Microarchitecture Targeting

# Baseline (default) — compatible with all AMD64 CPUs
GOAMD64=v1 go build ./...

# Haswell+ (2013) — CMPXCHG16B, POPCNT, SSE4.2
GOAMD64=v2 go build ./...

# AVX2 era — AVX2, BMI2, FMA
GOAMD64=v3 go build ./...

# AVX-512 — Knight's Landing+ / Zen4+
GOAMD64=v4 go build ./...

Higher levels enable SIMD instructions and intrinsics that the compiler can use for crypto, hashing, string operations, and math — but binaries will crash with SIGILL on older CPUs.

6.4 Race Detector

The race detector instruments memory accesses at compile time and detects data races at runtime.

# Build and run with race detection
go run -race ./cmd/server

# Test with race detection
go test -race ./...

# Build a race-instrumented binary
go build -race -o server-race ./cmd/server

Performance overhead: typically 5–10x slower, 5–10x more memory. Do not use in production. Use in:

  • CI test suites (essential)
  • Development builds
  • Dedicated race-detection test runs

The race detector supports linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64, freebsd/amd64.

6.5 Benchmarking

# Run all benchmarks
go test -bench=. -benchmem ./...

# Run specific benchmarks with count for statistical significance
go test -bench=BenchmarkServe -count=10 -benchmem ./pkg/server

# Compare benchmarks (using benchstat)
go test -bench=. -count=10 ./... > old.txt
# ... make changes ...
go test -bench=. -count=10 ./... > new.txt
go install golang.org/x/perf/cmd/benchstat@latest
benchstat old.txt new.txt

The testing.B API provides:

  • b.ReportAllocs() — report allocations per op
  • b.SetBytes(n) — set throughput denominator
  • b.RunParallel() — parallel benchmarking
  • b.ResetTimer() — exclude setup from timing
  • b.StopTimer() / b.StartTimer() — exclude sections

6.6 Memory Profiling

# Heap profile during tests
go test -memprofile=mem.pprof -bench=. ./...
go tool pprof mem.pprof

# Runtime memory stats in code
import "runtime"

var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("Alloc = %d MiB\n", m.Alloc/1024/1024)
fmt.Printf("TotalAlloc = %d MiB\n", m.TotalAlloc/1024/1024)
fmt.Printf("Sys = %d MiB\n", m.Sys/1024/1024)
fmt.Printf("NumGC = %d\n", m.NumGC)

6.7 GC Tuning

# Set GC target percentage (default 100 = GC when heap doubles)
GOGC=200 ./server          # Less frequent GC, more memory
GOGC=50 ./server           # More frequent GC, less memory
GOGC=off ./server          # Disable GC entirely

# Set memory limit (Go 1.19+)
GOMEMLIMIT=2GiB ./server   # Soft memory limit

# GC trace output
GODEBUG=gctrace=1 ./server
# Output format:
# gc 1 @0.012s 2%: 0.011+0.32+0.003 ms clock, 0.045+0.32/0.26/0+0.012 ms cpu, ...
GODEBUG setting Effect
gctrace=1 Print GC summary each cycle
gcpacertrace=1 Print GC pacer decisions
scavtrace=1 Print scavenger activity (memory returned to OS)
schedtrace=1000 Print scheduler state every 1000ms
scheddetail=1 Detailed scheduler info (with schedtrace)
allocfreetrace=1 Print every alloc/free (extremely verbose)

7. Security

7.1 Module Authentication and Supply Chain

Go's module system provides strong supply chain security through cryptographic verification.

go.sum and the Checksum Database:

Every module version downloaded is verified against cryptographic hashes stored in go.sum. The public checksum database (sum.golang.org) ensures that a given module version always maps to the same source code — preventing compromise even if the origin repository is tampered with.

# Verify all downloaded modules match go.sum
go mod verify

# Configure the checksum database
go env -w GOSUMDB=sum.golang.org                  # Default
go env -w GOSUMDB=off                              # Disable (not recommended)
go env -w GOSUMDB=sum.corp.example.com+key+hash    # Corporate mirror

# Exclude private modules from checksum verification
go env -w GONOSUMDB=*.corp.example.com,github.com/private-org/*

Warning

Disabling GOSUMDB removes tamper-detection for public modules. Any compromise of a module's Git repository or proxy would go undetected. Only disable for private modules that are not in the public checksum database.

7.2 Version Control Security

The GOVCS variable controls which version control systems are allowed for fetching modules:

# Default: git and hg for public, all for private
go env -w GOVCS="public:git|hg,private:all"

# Lock down to git only
go env -w GOVCS="*:git"

# Allow Subversion for a specific org
go env -w GOVCS="github.com/legacy-org:git|svn,*:git"

# Disable all VCS (modules must come from proxy)
go env -w GOVCS="*:off"
# Restrict Git protocols (defense against credential theft via malicious git:// URLs)
export GIT_ALLOW_PROTOCOL=https

7.3 FIPS 140 Mode

Go supports FIPS 140 validated cryptography for government and regulated environments.

# Build with FIPS 140 crypto
GOFIPS140=latest go build ./...

# Or a specific FIPS module version
GOFIPS140=v1.0.0 go build ./...

# Disable FIPS
GOFIPS140=off go build ./...

When FIPS mode is active, the crypto packages use FIPS-validated implementations, and non-compliant algorithms are restricted. The FIPS module source lives in lib/fips140/ within the Go repository.

Caution

FIPS 140 mode changes the behavior of the crypto package at a fundamental level. Some algorithms may be unavailable or behave differently. Test thoroughly before deploying FIPS-enabled binaries, and verify that your specific version carries the FIPS validation certificate (check the Go release notes).

7.4 CGO Security

CGO introduces C code execution into Go programs, expanding the attack surface. The CGO_*_ALLOW and CGO_*_DISALLOW variables provide defense in depth:

# Allow only specific flags
export CGO_CFLAGS_ALLOW="-D__EXTENSIONS__"
export CGO_LDFLAGS_ALLOW="-L/opt/openssl/lib"

# Disallow known-dangerous flags
export CGO_CFLAGS_DISALLOW="-fno-stack-protector"
export CGO_LDFLAGS_DISALLOW="-Wl,-rpath"

The Go toolchain has a built-in allowlist of safe compiler/linker flags. Flags outside this list are rejected unless explicitly allowed via _ALLOW. This prevents malicious #cgo directives in third-party packages from executing arbitrary commands through the C compiler.

Warning

Dependencies that use cgo can execute arbitrary C code at build time (via #cgo directives) and at runtime. Audit cgo-using dependencies carefully. Consider CGO_ENABLED=0 for services that don't need C interop — it eliminates an entire class of supply chain attacks.

7.5 Address and Memory Sanitizers

# Address Sanitizer — detects out-of-bounds access, use-after-free (in C code via cgo)
go build -asan ./...

# Memory Sanitizer — detects reads of uninitialized memory (Clang only)
go build -msan ./...

# Thread Sanitizer (race detector) — detects data races
go build -race ./...
Sanitizer Detects Overhead Requirements
-race Data races in Go code 5-10x CPU, 5-10x memory Linux/macOS/Windows (amd64, arm64)
-asan Memory errors in C/Go code 2x CPU, 3x memory Clang or GCC with ASan support
-msan Uninitialized reads in C code 2-3x CPU Clang only

7.6 Build Reproducibility

Reproducible builds ensure that the same source produces the same binary, bit-for-bit, enabling third-party verification:

go build -trimpath -buildvcs=false -ldflags="-s -w -buildid=" ./...
Concern Mitigation
Local paths in binary -trimpath
VCS metadata variation -buildvcs=false
Build ID variation -ldflags="-buildid="
Timestamp in binary Go does not embed timestamps by default
Module versions go.sum locks all dependency versions
Go toolchain version toolchain directive in go.mod + GOTOOLCHAIN

7.7 Insecure Module Fetching

The GOINSECURE variable allows fetching specific modules over plain HTTP (no TLS):

# Only for internal mirrors behind a firewall
go env -w GOINSECURE=*.corp.internal

Warning

Setting GOINSECURE disables both TLS verification and checksum validation for matching modules. This means man-in-the-middle attacks can inject malicious code. Only use this for internal registries on trusted networks, never for public modules.

7.8 Private Module Configuration

Complete private module setup:

# Modules matching these patterns bypass proxy and checksum DB
go env -w GOPRIVATE="github.com/myorg/*,*.corp.example.com"

# Authentication via .netrc
cat >> ~/.netrc <<EOF
machine github.com
  login my-token
  password x-oauth-basic
EOF
chmod 600 ~/.netrc

# Or via GOAUTH with a credential helper
go env -w GOAUTH="netrc command:git credential fill"

# Verify private module access
go list -m github.com/myorg/private-lib@latest

8. Developer Internals

8.1 Repository Structure

golang/go/
├── api/                    API compatibility definitions
│   ├── go1.txt             API surface for Go 1.0
│   ├── go1.1.txt           ...through each release
│   ├── go1.26.txt
│   └── next/               Proposed API additions for the next release
│       └── *.txt           One file per proposal/CL
├── doc/                    Documentation and release notes
│   ├── initial/            Template files for new release cycle
│   ├── next/               Accumulated release notes for next version
│   │   └── *.md            Per-CL or per-feature release note fragments
│   ├── asm.html            Go assembler guide
│   ├── go_mem.html         Go memory model
│   ├── go_spec.html        Go language specification
│   └── ...                 Various documentation files
├── lib/                    Support libraries
│   ├── fips140/            FIPS 140 validated crypto module
│   │   └── ...             Module source + verification artifacts
│   ├── time/               Timezone database
│   │   └── zoneinfo.zip    Bundled IANA timezone data
│   └── wasm/               WebAssembly support
│       └── wasm_exec.js    JS shim for Go WASM binaries
├── misc/                   Platform-specific tools and examples
│   ├── chrome/             GopherTool Chrome extension
│   │   └── gophertool/     Extension source
│   ├── cgo/                CGO usage examples
│   │   ├── gmp/            libgmp bindings example
│   │   ├── stdio/          stdio example
│   │   └── life/           Game of Life cgo example
│   ├── ios/                iOS exec wrapper
│   ├── go_android_exec/    Android exec wrapper (for testing)
│   └── wasm/               WASM helper scripts
├── src/                    ALL source code (Go + assembly)
│   ├── cmd/                Command-line tools
│   │   ├── go/             The go command itself
│   │   │   ├── internal/   Subpackages: modfetch, modload, work, test, etc.
│   │   │   ├── alldocs.go  Generated concatenation of all help text
│   │   │   └── main.go     Entry point
│   │   ├── compile/        Compiler (gc)
│   │   │   └── internal/   syntax, types2, ir, ssa, ssagen, amd64, arm64, ...
│   │   ├── link/           Linker
│   │   │   └── internal/   ld, loader, sym, objfile, arch-specific
│   │   ├── asm/            Assembler
│   │   ├── cgo/            C/Go bridge generator
│   │   ├── vet/            Static analysis driver
│   │   ├── trace/          Execution trace viewer
│   │   ├── cover/          Coverage tool
│   │   ├── pprof/          Profiling tool
│   │   ├── fix/            Code migration tool
│   │   ├── objdump/        Disassembler
│   │   ├── addr2line/      Address translator
│   │   ├── test2json/      Test output converter
│   │   ├── preprofile/     PGO preprocessor
│   │   ├── api/            API compatibility checker
│   │   ├── covdata/        Coverage data tool
│   │   ├── pack/           Archive tool
│   │   └── internal/       Shared internal packages
│   │       ├── objabi/     Object file ABI constants
│   │       ├── obj/        Object file format (per-arch)
│   │       ├── bio/        Buffered I/O for tools
│   │       ├── dwarf/      DWARF generation
│   │       ├── goobj/      Go object file reader/writer
│   │       ├── archive/    Archive format handler
│   │       ├── buildid/    Build ID computation
│   │       ├── pkgpath/    Package path encoding
│   │       └── ...
│   ├── runtime/            Runtime (594 files, 4.7M chars)
│   │   ├── proc.go         Goroutine scheduler (G, M, P)
│   │   ├── mgc.go          GC orchestration
│   │   ├── malloc.go       Memory allocator
│   │   ├── chan.go          Channel implementation
│   │   ├── select.go       Select statement
│   │   ├── stack.go        Stack management
│   │   ├── netpoll.go      Network poller (interface)
│   │   ├── netpoll_epoll.go  Linux epoll implementation
│   │   ├── netpoll_kqueue.go macOS/BSD kqueue implementation
│   │   ├── time.go         Timer heap
│   │   ├── panic.go        Panic/recover
│   │   ├── map.go          Map (hash table) implementation
│   │   ├── slice.go        Slice operations
│   │   ├── string.go       String operations
│   │   ├── symtab.go       Symbol table
│   │   ├── traceback.go    Stack trace generation
│   │   ├── asm_amd64.s     AMD64 assembly (scheduler, syscall)
│   │   ├── asm_arm64.s     ARM64 assembly
│   │   └── ...             Per-OS, per-arch assembly files
│   ├── net/                Networking
│   │   ├── http/           HTTP client and server (70 files, 1.5M chars)
│   │   │   ├── server.go   HTTP server
│   │   │   ├── client.go   HTTP client
│   │   │   ├── transport.go Connection pooling, HTTP/2
│   │   │   ├── h2_bundle.go Bundled HTTP/2 implementation
│   │   │   ├── pprof/      Profiling HTTP handlers
│   │   │   ├── httputil/   Reverse proxy, dump
│   │   │   └── ...
│   │   ├── rpc/            RPC framework
│   │   └── ...             DNS, TCP, UDP, Unix sockets, etc.
│   ├── crypto/             Cryptographic packages
│   │   ├── tls/            TLS 1.2/1.3 implementation
│   │   ├── x509/           X.509 certificate handling
│   │   ├── aes/, sha256/   Algorithm implementations
│   │   └── ...
│   ├── syscall/            System calls (294 files, 5.2M chars)
│   │   ├── syscall_linux.go
│   │   ├── zsyscall_linux_amd64.go  (generated)
│   │   └── ...             Per-OS, per-arch syscall definitions
│   ├── internal/           Internal packages (not importable outside std)
│   │   ├── abi/            ABI definitions
│   │   ├── cpu/            CPU feature detection
│   │   ├── godebug/        GODEBUG runtime settings
│   │   ├── fuzz/            Fuzzing engine
│   │   ├── trace/          Trace format reader
│   │   └── ...             ~60 internal packages
│   ├── fmt/                Formatting (14 files, 224K chars)
│   ├── encoding/           Serialization: json, xml, gob, csv, binary, etc.
│   ├── sync/               Mutex, RWMutex, WaitGroup, Once, Pool, Map
│   ├── testing/            Test framework (testing.T, testing.B, testing.F)
│   ├── reflect/            Runtime reflection
│   ├── context/            Context propagation
│   ├── io/                 I/O interfaces and utilities
│   ├── os/                 OS interaction (files, processes, env)
│   ├── flag/               Command-line flag parsing
│   ├── embed/              File embedding (//go:embed)
│   ├── log/slog/           Structured logging
│   ├── time/               Time, duration, timezone handling
│   ├── go/                 Go language tooling
│   │   ├── ast/            Abstract syntax tree
│   │   ├── parser/         Go source parser
│   │   ├── types/          Type checker
│   │   ├── doc/            Documentation extractor
│   │   ├── format/         Source formatter
│   │   ├── printer/        AST printer
│   │   ├── scanner/        Lexer
│   │   └── token/          Token definitions
│   └── ...                 ~150 packages total
├── test/                   Compiler and runtime test suite
│   ├── fixedbugs/          Regression tests (1815 files!)
│   ├── codegen/            Code generation verification tests
│   ├── typeparam/          Generics (type parameter) tests
│   ├── abi/                ABI-related tests
│   ├── syntax/             Parser tests
│   ├── bench/              Benchmark tests
│   └── ...                 Additional test categories
├── go.mod                  Module definition (module std, go 1.27)
├── go.sum                  Dependency checksums
├── LICENSE                 BSD 3-clause license
├── PATENTS                 Additional patent grant
├── CONTRIBUTING.md         Contribution guide (→ Gerrit)
├── SECURITY.md             Security reporting policy
└── codereview.cfg          Gerrit code review configuration

8.2 Compiler Pipeline Deep Dive

The gc compiler (src/cmd/compile/) transforms Go source into machine code through a multi-stage pipeline:

Stage 1: Parsing → AST

Package: src/cmd/compile/internal/syntax/

The parser reads Go source files and produces a syntax tree. It handles the complete Go grammar including generics syntax. The scanner/lexer tokenizes input, and the recursive descent parser builds the tree.

source.go → Scanner (tokens) → Parser (AST) → syntax.File

Stage 2: Type Checking

Package: src/cmd/compile/internal/types2/

The type checker (types2) is the successor of go/types, redesigned to work with the compiler's syntax tree. It resolves identifiers, infers types, checks assignability, validates generic constraints, and instantiates generic functions/types.

Stage 3: IR Construction

Package: src/cmd/compile/internal/ir/

The type-checked syntax tree is converted to the compiler's intermediate representation (IR). This is a graph of nodes representing Go operations at a higher level than SSA but lower than syntax.

Stage 4: Inlining and Escape Analysis

Packages: src/cmd/compile/internal/inline/, src/cmd/compile/internal/escape/

  • Inlining: small functions are inlined at their call sites. The inlining budget considers function size, call frequency (boosted by PGO), and recursion depth.
  • Escape analysis: determines whether variables can live on the stack (cheap) or must be heap-allocated (expensive). Reports available via go build -gcflags="-m".
# See inlining decisions
go build -gcflags="-m" ./pkg/server 2>&1 | grep "inlining"

# See escape analysis
go build -gcflags="-m" ./pkg/server 2>&1 | grep "escapes to heap"

Stage 5: SSA Generation

Packages: src/cmd/compile/internal/ssagen/, src/cmd/compile/internal/ssa/

The IR is lowered to Static Single Assignment form. Each SSA value has exactly one definition, making optimizations straightforward.

# Visualize SSA for a function
GOSSAFUNC=main.handleRequest go build ./cmd/server
# Open ssa.html in a browser to see all SSA passes

Stage 6: SSA Optimization Passes

The SSA optimizer runs dozens of passes including:

Pass Purpose
opt Algebraic simplifications
cse Common subexpression elimination
nilcheck Nil check elimination
prove Bounds check elimination via value range analysis
fuse Basic block fusion
dse Dead store elimination
writebarrier GC write barrier insertion
lower Architecture-specific lowering
regalloc Register allocation
schedule Instruction scheduling

Stage 7: Machine Code Generation

Packages: src/cmd/compile/internal/amd64/, arm64/, 386/, etc.

Architecture-specific backends emit machine instructions from the lowered SSA. Each architecture has its own instruction selection rules and register conventions.

Stage 8: Object File Output

The compiler writes object files in Go's internal format. These contain machine code, symbol definitions, relocations, DWARF debug info, and metadata for the linker.

8.3 Runtime Architecture

The Go runtime (src/runtime/) is linked into every Go binary. Understanding its internals is essential for performance tuning and debugging.

Goroutine Scheduler (M:N)

The scheduler multiplexes goroutines (G) onto OS threads (M) using a work-stealing algorithm mediated by logical processors (P).

┌───────────────────────────────────────────────┐
│                   Go Program                   │
│                                               │
│  G1  G2  G3  G4  G5  G6  ... Gn (goroutines) │
│   │   │   │   │   │   │                      │
│   └───┴───┼───┴───┴───┘                      │
│           │                                   │
│     ┌─────┴─────┐                             │
│     │ Run Queue │ (global + per-P local)      │
│     └─────┬─────┘                             │
│           │                                   │
│   ┌───────┼───────┐                           │
│   P0      P1      P2  (GOMAXPROCS processors) │
│   │       │       │                           │
│   M0      M1      M2  (OS threads)            │
│   │       │       │                           │
└───┼───────┼───────┼───────────────────────────┘
    │       │       │
    CPU0    CPU1    CPU2  (hardware)

Key concepts:

  • G (goroutine): a lightweight thread with its own stack, starting at 8KB, growing as needed up to 1GB.
  • M (machine): an OS thread. Created on demand, cached when idle. Default max: 10,000.
  • P (processor): a logical processor that mediates between G and M. Count = GOMAXPROCS (default: number of CPU cores).
  • Work stealing: when a P's local run queue is empty, it steals goroutines from other P's queues or the global queue.
  • Preemption: goroutines are preempted at safe points (since Go 1.14, asynchronous preemption on most platforms via signals).

Key source files:

  • proc.go — scheduler core, schedule(), findRunnable(), execute()
  • runtime2.go — G, M, P struct definitions
  • preempt.go — preemption logic
  • lock_*.go — platform-specific locking

Garbage Collector

The GC is a concurrent, tri-color, mark-sweep collector with non-generational design.

GC Cycle:
  ┌─────────────────────────────────────────────────┐
  │  Mark Setup  │  Concurrent Mark  │  Mark Term.  │
  │  (STW ~µs)  │  (concurrent)     │  (STW ~µs)   │
  └──────────────┴───────────────────┴──────────────┘
                                          │
                                    Sweep (concurrent,
                                    lazy on allocation)
  • Tri-color marking: objects are white (unmarked), grey (marked, refs unchecked), or black (marked, refs checked).
  • Write barrier: tracks pointer updates during concurrent marking to maintain the invariant that no black object points to a white object.
  • Pacing: the GC pacer determines when to start the next cycle based on GOGC (target ratio of new allocation to live heap) and GOMEMLIMIT (soft memory limit).
  • STW pauses: typically under 1ms, often under 100µs. The two brief stop-the-world phases handle root marking setup and termination.

Key source files:

  • mgc.go — GC orchestration, gcStart(), pacing
  • mgcmark.go — marking logic
  • mgcsweep.go — sweep logic
  • mgcwork.go — grey object workqueue
  • mbarrier.go — write barrier
  • mgcpacer.go — GC pacing algorithm

Memory Allocator

The allocator is based on tcmalloc, organized in a hierarchy:

┌──────────────┐
│ goroutine    │ Tiny allocs (< 16B, no pointers) → tiny allocator
│              │ Small allocs (< 32KB) → mcache → mcentral → mheap
│              │ Large allocs (≥ 32KB) → mheap directly
└──────┬───────┘
       │
┌──────┴───────┐
│ mcache       │ Per-P cache of mspan pointers (one per size class)
│ (per-P)      │ Lock-free fast path
└──────┬───────┘
       │
┌──────┴───────┐
│ mcentral     │ Per-size-class central list of mspans
│ (shared)     │ Lock per size class
└──────┬───────┘
       │
┌──────┴───────┐
│ mheap        │ Manages page-level allocation
│ (global)     │ Treap of free page runs
└──────┬───────┘
       │
       OS (mmap/VirtualAlloc)

Size classes: 67 classes from 8 bytes to 32KB. Objects are allocated from spans (contiguous pages) dedicated to a single size class.

Key source files:

  • malloc.go — mallocgc(), the allocator entry point
  • mheap.go — page-level heap management
  • mcache.go — per-P caches
  • mcentral.go — central span lists
  • sizeclasses.go — size class definitions (generated)
  • mfixalloc.go — fixed-size allocator for runtime structures

Stack Management

Goroutine stacks are segmented and growable:

  • Initial size: 8KB (configurable with runtime/debug.SetMaxStack)
  • Growth: when a function's stack frame won't fit, the runtime allocates a new, larger stack (2x), copies the old stack, and updates all pointers.
  • Maximum: 1GB by default
  • Shrinking: the GC can shrink stacks during collection

Key source file: stack.go

Channel Implementation

Channels (chan T) are implemented as a circular buffer with a mutex and two wait queues (senders and receivers).

hchan struct:
  ┌─────────────────────────┐
  │ buf     *[dataqsiz]T    │ Circular buffer
  │ dataqsiz uint           │ Buffer capacity
  │ qcount  uint            │ Current count
  │ sendx   uint            │ Send index
  │ recvx   uint            │ Receive index
  │ recvq   waitq           │ Blocked receivers
  │ sendq   waitq           │ Blocked senders
  │ lock    mutex            │
  └─────────────────────────┘

Unbuffered channels (make(chan T)) have dataqsiz=0 and always block until a matching sender/receiver arrives. The runtime uses gopark/goready to suspend/resume goroutines on channel operations.

Key source file: chan.go

Netpoller

The netpoller integrates OS-level I/O multiplexing (epoll, kqueue, IOCP) with the goroutine scheduler. When a goroutine blocks on a network operation, it parks itself and the netpoller resumes it when the I/O is ready — without blocking an OS thread.

OS Mechanism Source file
Linux epoll netpoll_epoll.go
macOS, BSD kqueue netpoll_kqueue.go
Windows IOCP netpoll_windows.go
Solaris event ports netpoll_solaris.go
AIX pollset netpoll_aix.go

8.4 Standard Library Inventory

The standard library spans approximately 150 packages. Key packages by category:

Core Language Support

Package Files Size Purpose
runtime 594 4.7M Scheduler, GC, memory, stacks, channels, maps
reflect ~20 ~300K Runtime type reflection
unsafe 1 ~2K Pointer arithmetic, type circumvention
builtin 1 ~10K Built-in function documentation
errors ~5 ~15K Error wrapping, Is, As, Join
context ~4 ~30K Cancellation and value propagation
sync 26 126K Mutex, RWMutex, WaitGroup, Once, Pool, Map
sync/atomic ~10 ~40K Atomic operations

I/O and Formatting

Package Files Size Purpose
fmt 14 224K Formatted I/O (Printf, Sprintf, Scanf, etc.)
io ~10 ~60K I/O interfaces (Reader, Writer, Closer)
io/fs ~8 ~30K Filesystem interfaces
bufio ~5 ~40K Buffered I/O
bytes ~5 ~50K Byte slice manipulation
strings ~10 ~60K String manipulation
strconv ~15 ~120K String/number conversions
os ~30 ~200K OS-level file, process, environment operations
path/filepath ~10 ~50K OS-specific file path manipulation
embed ~4 ~20K File embedding (//go:embed)

Networking

Package Files Size Purpose
net ~50 ~500K TCP, UDP, Unix sockets, DNS resolution
net/http 70 1.5M HTTP client and server (HTTP/1.1, HTTP/2)
net/http/pprof ~3 ~15K Profiling HTTP handlers
net/http/httputil ~5 ~30K Reverse proxy, request/response dumping
net/rpc ~8 ~40K RPC framework
net/url ~3 ~30K URL parsing

Encoding and Serialization

Package Files Size Purpose
encoding/json ~15 ~200K JSON encoding/decoding
encoding/xml ~10 ~150K XML encoding/decoding
encoding/gob ~10 ~100K Go binary encoding
encoding/csv ~4 ~25K CSV reading/writing
encoding/binary ~4 ~30K Binary encoding (big/little endian)
encoding/base64 ~2 ~15K Base64 encoding
encoding/hex ~2 ~10K Hex encoding

Cryptography

Package Files Size Purpose
crypto/tls ~30 ~300K TLS 1.2/1.3 implementation
crypto/x509 ~15 ~200K X.509 certificate parsing and validation
crypto/aes ~5 ~20K AES encryption
crypto/sha256 ~3 ~10K SHA-256 hashing
crypto/rsa ~5 ~40K RSA encryption/signing
crypto/ecdsa ~3 ~20K ECDSA signing
crypto/ed25519 ~3 ~15K Ed25519 signing
crypto/rand ~3 ~10K Cryptographic random number generation

Testing and Tooling

Package Files Size Purpose
testing ~15 ~150K Test framework (T, B, F, M)
testing/fstest ~2 ~15K Filesystem testing
testing/iotest ~2 ~10K I/O testing helpers
testing/slogtest ~2 ~10K slog handler testing
go/ast ~5 ~60K AST types
go/parser ~5 ~50K Go source parser
go/types ~30 ~300K Type checker
go/format ~2 ~10K Source formatting
go/doc ~5 ~40K Documentation extraction

System

Package Files Size Purpose
syscall 294 5.2M Raw system call interface (per-OS, per-arch)
os/exec ~5 ~40K External command execution
os/signal ~5 ~20K Signal handling
os/user ~5 ~20K User/group lookup
flag ~4 ~40K Command-line flag parsing
log ~5 ~20K Basic logging
log/slog ~15 ~80K Structured logging (Go 1.21+)
time 38 404K Time, duration, timer, timezone

Data Structures

Package Files Size Purpose
slices ~5 ~30K Generic slice operations
maps ~3 ~10K Generic map operations
sort ~5 ~40K Sorting algorithms
container/heap ~2 ~5K Heap (priority queue)
container/list ~2 ~10K Doubly-linked list
container/ring ~2 ~5K Circular list
cmp ~2 ~5K Ordered comparison
iter ~3 ~15K Iterator protocol (Go 1.23+)
unique ~3 ~10K Value interning (Go 1.23+)

Other Notable Packages

Package Purpose
regexp Regular expressions (RE2 syntax)
math Mathematical functions
math/big Arbitrary precision arithmetic
math/rand/v2 Pseudo-random number generation
compress/gzip, flate, zlib Compression
archive/tar, zip Archive formats
image, image/png, image/jpeg Image encoding/decoding
html/template, text/template Template engines
database/sql SQL database interface
plugin Plugin loading (Linux, macOS, FreeBSD)
debug/buildinfo, dwarf, elf, macho, pe Binary introspection
expvar Public variables (exported as JSON)
runtime/pprof Profiling API
runtime/trace Execution tracing API
runtime/debug Debugging facilities (SetGCPercent, SetMemoryLimit, etc.)
weak Weak references (Go 1.24+)
structs Struct layout control (Go 1.24+)

8.5 Built-in Functions

These are documented in src/builtin/builtin.go and available without importing:

Function Signature Purpose
append func append(slice []T, elems ...T) []T Appends elements to a slice
copy func copy(dst, src []T) int Copies elements between slices
delete func delete(m map[K]V, key K) Deletes a map entry
len func len(v T) int Length of string, slice, array, map, channel
cap func cap(v T) int Capacity of slice, array, channel
make func make(t T, size ...int) T Allocates slice, map, or channel
new func new(T) *T Allocates zeroed value, returns pointer
complex func complex(r, i FloatType) ComplexType Constructs a complex number
real func real(c ComplexType) FloatType Real part of complex number
imag func imag(c ComplexType) FloatType Imaginary part of complex number
clear func clear(t T) Clears map or zeroes slice elements
close func close(c chan<- T) Closes a channel
panic func panic(v any) Stops normal execution
recover func recover() any Regains control of a panicking goroutine
print func print(args ...T) Low-level print (for bootstrapping/debugging)
println func println(args ...T) Low-level println
min func min(x T, y ...T) T Minimum of ordered values (Go 1.21+)
max func max(x T, y ...T) T Maximum of ordered values (Go 1.21+)

8.6 Compiler Directives and Pragmas

Go supports several //go: directives that control compilation behavior:

Directive Scope Purpose
//go:build expr File Build constraint (include/exclude file from build)
//go:generate cmd File Code generation command (run by go generate)
//go:embed pattern Variable Embed file contents into the binary
//go:noinline Function Prevent inlining
//go:nosplit Function Prevent stack split check (for low-level runtime code)
//go:noescape Function Declaration-only function does not let pointers escape
//go:norace Function Omit race detector instrumentation
//go:linkname local remote Variable/Function Link a local name to a remote symbol
//go:wasmexport name Function Export function for WebAssembly host
//export name Function Export function for C (used with cgo)
//go:debug key=value Package main Set default GODEBUG value
// Example: embed a file
//go:embed config.json
var configData []byte

// Example: code generation
//go:generate stringer -type=Status

// Example: prevent inlining for benchmarking
//go:noinline
func processItem(item *Item) error { ... }

Note

//go:linkname is considered unsafe and its use outside the standard library is discouraged. Starting from Go 1.23, packages using //go:linkname to access internal symbols may break without notice. The directive requires import "unsafe" in the same file.

8.7 Linker Deep Dive

The Go linker (src/cmd/link/) combines compiled object files with the runtime into a final executable. Understanding its operation is important for debugging link errors and optimizing binary size.

Linker pipeline:

Object files (.o) + Runtime package
    │
    ▼
Symbol Resolution — resolve all references between packages
    │
    ▼
Dead Code Elimination — remove unreachable functions/data
    │
    ▼
DWARF Generation — debug info (unless -w)
    │
    ▼
Relocation — fix up addresses for final layout
    │
    ▼
Output — ELF (Linux), Mach-O (macOS), PE (Windows), Plan 9 a.out

Internal vs external linking:

Mode When used Description
Internal Default for pure Go Go's own linker handles everything
External CGO, -linkmode external, certain flags Go produces a .o, system linker (gcc/clang) produces final binary

External linking is forced when:

  • CGO is used (by default)
  • -buildmode=c-shared or -buildmode=c-archive
  • -linkmode external is specified
  • Sanitizers are enabled (-race, -asan, -msan)

Binary size optimization:

# Baseline
go build -o server ./cmd/server
ls -lh server  # e.g., 12M

# Strip debug info
go build -ldflags="-s -w" -o server-stripped ./cmd/server
ls -lh server-stripped  # e.g., 8M (30-40% reduction)

# Further compression with UPX (external tool)
upx --best server-stripped  # e.g., 3M (use with caution — breaks some tools)

Analyzing binary contents:

# Show which packages contribute to binary size
go build -o server ./cmd/server
go tool nm server | sort -n -k 2 | tail -20   # Largest symbols
go tool objdump -s main.main server             # Disassemble a function

# Detailed size breakdown (requires go-binsize-viz or similar)
go tool nm -size server | awk '{print $2, $4}' | sort -rn | head -30

8.8 Code Patterns and Conventions

Internal packages: any package in a directory named internal/ is only importable by packages rooted at the parent of internal/. This is enforced by the compiler and provides encapsulation without making symbols unexported.

src/cmd/compile/internal/ssa/   → only importable by src/cmd/compile/...
src/internal/cpu/               → only importable by src/...

Vendor directory: the standard library vendors its tool dependencies in src/cmd/vendor/. This directory is managed by go mod vendor and ensures that tool builds are hermetic.

Generated code: many files are generated from templates or data:

  • syscall/zsyscall_*.go — generated system call wrappers
  • runtime/sizeclasses.go — generated size class tables
  • cmd/go/alldocs.go — generated from help text
  • *_string.go — generated by stringer

Test conventions:

  • Unit tests: *_test.go alongside source
  • External tests: package foo_test (black-box testing of exported API)
  • Internal tests: package foo (white-box testing with access to unexported symbols)
  • Table-driven tests: idiomatic Go pattern used extensively throughout the stdlib
  • TestMain: used for test setup/teardown that needs to run once

8.8 Testing Strategy

The Go repository has a multi-layered testing approach:

Standard library tests (src/ — *_test.go files): Every standard library package has tests alongside its source. These are the primary correctness tests.

# Run all standard library tests
cd $GOROOT/src
go test ./...

# Run tests for a specific package
go test runtime
go test net/http
go test -v -run TestSpecific crypto/tls

Compiler and runtime regression tests (test/): The test/ directory contains thousands of test files that are compiled and executed to verify compiler correctness:

  • test/fixedbugs/ — 1815 regression test files, each tied to a specific bug fix
  • test/codegen/ — verify generated assembly for specific patterns
  • test/typeparam/ — generics-related tests
  • test/abi/ — calling convention tests
  • test/syntax/ — parser error tests
  • test/bench/ — compiler benchmark tests
# Run the compiler test suite
cd $GOROOT/test
go run run.go

Script-based tests (src/cmd/go/testdata/script/): The go command has extensive script-based integration tests that simulate real workflows:

# Example script test structure
env GOFLAGS=''
go build -o foo.exe .
exec ./foo.exe
stdout 'hello world'

Fuzzing:

func FuzzParseJSON(f *testing.F) {
    f.Add([]byte(`{"key": "value"}`))
    f.Fuzz(func(t *testing.T, data []byte) {
        var v interface{}
        json.Unmarshal(data, &v)
    })
}

8.9 Contributing to Go

Go uses a Gerrit-based code review system, not GitHub pull requests.

  1. Sign the CLA — a Contributor License Agreement is required
  2. Clone from Gerrit: git clone https://go.googlesource.com/go
  3. Create a branch: git checkout -b my-change
  4. Make changes and test: cd src && ./all.bash
  5. Commit with Change-Id: git codereview change (installs a commit-msg hook that adds Change-Id)
  6. Mail for review: git codereview mail
  7. Iterate on feedback via the Gerrit web UI

Release notes are added as individual Markdown files in doc/next/ — one file per change, merged into the release notes document during the release cycle.

API additions must be added to api/next/ as well, so the cmd/api compatibility checker can verify them.


9. Integration Points

9.1 CGO: Go ↔ C Interop

CGO bridges Go and C code, enabling Go programs to call C functions and vice versa.

Calling C from Go:

package main

/*
#include <stdio.h>
#include <stdlib.h>

void greet(const char* name) {
    printf("Hello, %s!\n", name);
}
*/
import "C"
import "unsafe"

func main() {
    name := C.CString("World")
    defer C.free(unsafe.Pointer(name))
    C.greet(name)
}

Calling Go from C (//export directive):

package main

import "C"

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

func main() {}

Build as a C library:

go build -buildmode=c-archive -o libgo.a .
# or
go build -buildmode=c-shared -o libgo.so .

CGO directives in Go source:

// #cgo CFLAGS: -I/opt/include
// #cgo LDFLAGS: -L/opt/lib -lfoo
// #cgo linux LDFLAGS: -lm
// #cgo pkg-config: libpng
import "C"
Directive Purpose
#cgo CFLAGS: C compiler flags
#cgo LDFLAGS: Linker flags
#cgo pkg-config: Use pkg-config for flags
#cgo CPPFLAGS: C preprocessor flags
#cgo CXXFLAGS: C++ compiler flags
#cgo FFLAGS: Fortran compiler flags
#cgo OS CFLAGS: OS-conditional flags

9.2 SWIG: Go ↔ C++ Interop

For C++ interoperability, Go supports SWIG (Simplified Wrapper and Interface Generator). Place .swig or .swigcxx files in Go package directories:

mypackage/
├── mypackage.go
├── mypackage.swigcxx    ← SWIG interface file
└── mypackage.h          ← C++ header

The go build command automatically invokes SWIG when it finds these files.

9.3 WebAssembly

Go compiles to WebAssembly for browser and WASI environments.

Browser (js/wasm):

GOOS=js GOARCH=wasm go build -o main.wasm ./cmd/wasm-app

# Copy the JavaScript support file
cp "$(go env GOROOT)/lib/wasm/wasm_exec.js" .
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
    go.run(result.instance);
});
</script>

WASI (wasip1/wasm):

GOOS=wasip1 GOARCH=wasm go build -o main.wasm ./cmd/wasi-app

# Run with a WASI runtime
wasmtime main.wasm
wazero run main.wasm

Exporting functions to the host:

//go:wasmexport add
func add(a, b int32) int32 {
    return a + b
}

Note

The wasm_exec.js shim requires globalThis.crypto to be available. In environments where it is not (e.g., Node.js without --experimental-global-webcrypto), a polyfill is required. The error message "globalThis.crypto is not available, polyfill required" indicates this condition.

9.4 Android and iOS

Android:

# Set up Android NDK cross-compiler
export CC=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang
CGO_ENABLED=1 GOOS=android GOARCH=arm64 go build -o myapp ./cmd/app

The misc/go_android_exec wrapper executes Go test binaries on Android devices via adb.

iOS:

CGO_ENABLED=1 GOOS=ios GOARCH=arm64 go build -buildmode=c-archive -o mylib.a ./cmd/lib

The misc/ios directory provides an exec wrapper for running Go test binaries on iOS simulators and devices.

9.5 Plugin System

Go's plugin system allows loading shared objects at runtime:

# Build a plugin
go build -buildmode=plugin -o myplugin.so ./plugins/myplugin
// Loading and using a plugin
p, err := plugin.Open("myplugin.so")
if err != nil {
    log.Fatal(err)
}

sym, err := p.Lookup("Handler")
if err != nil {
    log.Fatal(err)
}

handler, ok := sym.(func(string) string)
if !ok {
    log.Fatal("unexpected type")
}

result := handler("input")

Limitations:

  • Supported on Linux (amd64, arm64), macOS (amd64, arm64), and FreeBSD (amd64)
  • Plugin and host must be built with the same Go version
  • All dependencies must have compatible versions
  • Plugins cannot be unloaded

9.6 Build System Integration

JSON output for tooling:

# Package metadata as JSON
go list -json ./...

# Test results as JSON
go test -json ./...

# Build events as JSON
go build -json ./...

# Module dependency graph
go mod graph

# Why is a module needed?
go mod why -m golang.org/x/net

go:generate for code generation:

//go:generate stringer -type=Status
//go:generate protoc --go_out=. myservice.proto
//go:generate mockgen -source=interface.go -destination=mock_interface.go
go generate ./...

9.7 Embedding Files

The embed package allows embedding files and directories into Go binaries at compile time:

import "embed"

// Single file
//go:embed config.json
var configBytes []byte

// Single file as string
//go:embed version.txt
var version string

// Directory tree
//go:embed static/*
var staticFiles embed.FS

// Multiple patterns
//go:embed templates/*.html assets/*.css assets/*.js
var webContent embed.FS

The embedded filesystem implements io/fs.FS and can be used with net/http.FileServer, html/template, and any function accepting an fs.FS.


10. Troubleshooting

Error: cannot find GOROOT directory

Cause: The Go installation directory cannot be located. Either GOROOT is set incorrectly, or the go binary is not in a standard location relative to the Go installation.

Solution:

# Check what Go thinks GOROOT is
go env GOROOT

# If wrong, set it explicitly
export GOROOT=/usr/local/go

# Or remove any stale GOROOT and let Go auto-detect
unset GOROOT

Prevention: Do not set GOROOT manually unless you have multiple Go installations. The go binary infers GOROOT from its own location.


Error: go: go.mod file not found in current directory or any parent directory

Cause: Running a Go command that requires module context (like go build or go test) outside of a module — no go.mod exists in the current directory or any ancestor.

Solution:

# Initialize a new module
go mod init example.com/myproject

# Or navigate to the correct directory
cd /path/to/project-with-go-mod

Prevention: Always work inside a module directory. Use go work for multi-module development.


Error: package XXX is not in std

Cause: Attempting to import a package using a standard library path that does not exist, or importing an internal/ package from outside its allowed tree.

Solution: Verify the import path against the standard library documentation. Internal packages like internal/cpu or cmd/compile/internal/ssa cannot be imported by user code.

Prevention: Use go doc to verify package paths: go doc net/http.


Error: go: module requires Go >= 1.XX (running 1.YY)

Cause: The go.mod file specifies a minimum Go version higher than the installed Go version.

Solution:

# Upgrade Go
go install golang.org/dl/go1.XX@latest
go1.XX download

# Or use GOTOOLCHAIN=auto to automatically download
go env -w GOTOOLCHAIN=auto

Prevention: Set GOTOOLCHAIN=auto in development environments for seamless toolchain upgrades.


Error: build constraints exclude all Go files

Cause: No Go files in the package match the current GOOS/GOARCH or build tag combination. All files have //go:build constraints that exclude the current platform.

Solution:

# Check what files exist and their constraints
ls *.go
head -5 *.go  # Look for //go:build lines

# Build for the correct platform
GOOS=linux go build ./...

# Or add the required build tag
go build -tags=integration ./...

Prevention: Review build constraints when creating platform-specific code.


Error: verifying module: checksum mismatch

Cause: A downloaded module's content does not match the hash in go.sum. This can indicate tampering, a corrupted cache, or a module author who re-tagged a release.

Solution:

# Clear the module cache
go clean -modcache

# Re-download and verify
go mod download

# If the mismatch is legitimate (author re-tagged), update go.sum
go mod tidy

Caution

A checksum mismatch on a previously-working module is a potential supply chain attack indicator. Investigate before blindly clearing the cache. Compare the failing hash with known-good values, and check if the module's repository shows unexpected force-pushes.

Prevention: Pin modules with go.sum. Use GONOSUMDB only for genuinely private modules.


Error: fatal error: all goroutines are asleep - deadlock!

Cause: Every goroutine is blocked (waiting on a channel, mutex, or other synchronization primitive) and no goroutine can make progress. The runtime detects this and panics.

Solution: Analyze the stack trace printed with the error. Common causes:

  • Sending on an unbuffered channel with no receiver
  • Waiting on a WaitGroup that was never decremented
  • Mutex lock ordering violations (A→B in one goroutine, B→A in another)
# Run with race detector to catch related issues
go run -race ./...

Prevention: Design goroutine lifecycles with clear ownership. Use context.Context for cancellation. Consider select with default or timeouts to prevent permanent blocking.


Error: race detected during execution of test

Cause: The race detector found concurrent, unsynchronized access to a shared variable during test execution.

Solution: The race detector output shows the two conflicting accesses with full stack traces. Protect the shared variable with sync.Mutex, sync/atomic, or restructure to avoid sharing.

Prevention: Always run go test -race in CI. Fix all race conditions — even "benign" ones can cause unpredictable behavior.


Error: signal: killed (or OOM)

Cause: The OS killed the process, usually due to exceeding memory limits (OOM killer on Linux) or a cgroup memory limit.

Solution:

# Set a soft memory limit
GOMEMLIMIT=1GiB ./myapp

# Reduce GC pressure by lowering GOGC
GOGC=50 ./myapp

# Profile memory usage
go tool pprof http://localhost:8080/debug/pprof/heap

Prevention: Use GOMEMLIMIT in containerized environments to keep Go's memory usage within container limits. Profile heap usage periodically.


Error: too many open files

Cause: The process hit the OS file descriptor limit (ulimit -n). Common with many concurrent network connections or file operations.

Solution:

# Increase the file descriptor limit
ulimit -n 65536

# Or in systemd:
# [Service]
# LimitNOFILE=65536

In Go code, ensure connections and files are closed promptly:

resp, err := http.Get(url)
if err != nil { return err }
defer resp.Body.Close()  // Critical!

Prevention: Use connection pools, close resources with defer, and set appropriate OS limits.


Error: transport: error while dialing: connection refused

Cause: TCP connection to the target host/port failed. The server is not running, firewall is blocking, or the address is wrong.

Solution: Verify the server is running and reachable. Check firewall rules and DNS resolution. Use net.DialTimeout instead of net.Dial to avoid long hangs.

Prevention: Implement retry logic with exponential backoff. Use health checks to detect server readiness.


Error: connection is shut down

Cause: In net/rpc, the client attempted to make an RPC call on a connection that has already been closed.

Solution: Check for connection lifecycle issues. The server may have closed the connection, or the client may have called client.Close() prematurely.

Prevention: Implement reconnection logic. Check client.Call() errors for rpc.ErrShutdown and reconnect.


Error: rpc: service already defined

Cause: Calling rpc.Register() or rpc.RegisterName() with a service that has already been registered.

Solution: Register each service only once, typically during initialization.

Prevention: Use sync.Once or register all services in a single init() function.


Error: time: invalid number / time: bad value for field

Cause: Parsing a time string with time.Parse() where the input does not match the layout format.

Solution: Go uses a reference time (Mon Jan 2 15:04:05 MST 2006) for layouts. The layout must use these exact reference values:

// Correct
t, err := time.Parse("2006-01-02T15:04:05Z07:00", "2024-03-15T10:30:00-05:00")

// Wrong — using arbitrary numbers
t, err := time.Parse("YYYY-MM-DD", "2024-03-15")  // Will fail

Prevention: Use predefined constants (time.RFC3339, time.RFC1123, etc.) when possible. Test parsing with sample inputs.


Error: year outside of range [0,9999]

Cause: Formatting a time.Time value with RFC 3339 when the year is negative or exceeds 9999. This is a strict compliance check for RFC 3339.

Solution: Validate time values before formatting. Use a different layout format for historical or far-future dates.


Error: unknown time zone

Cause: time.LoadLocation() cannot find the specified timezone name. The timezone database is not available or the name is misspelled.

Solution:

# Ensure timezone data is installed
# Linux:
sudo apt-get install tzdata

# Or embed timezone data in the binary:
import _ "time/tzdata"
// Embed timezone data for portable binaries
import _ "time/tzdata"

loc, err := time.LoadLocation("America/New_York")

Prevention: Import time/tzdata in applications that must work on minimal containers (Alpine, scratch) without OS timezone data. Go bundles timezone data in lib/time/zoneinfo.zip.


Error: malformed time zone information

Cause: The timezone database file (zoneinfo.zip or system timezone files) is corrupted or in an unexpected format.

Solution: Reinstall the tzdata package on the OS, or ensure lib/time/zoneinfo.zip in GOROOT is intact. Using import _ "time/tzdata" avoids dependency on OS files entirely.


Error: corrupt zip file (timezone data)

Cause: The bundled zoneinfo.zip file is corrupted, possibly due to a partial Go installation or disk issue.

Solution: Reinstall Go or copy a valid zoneinfo.zip from a known-good installation to $GOROOT/lib/time/.


Error: image: unknown format

Cause: Attempting to decode an image with image.Decode() without importing the format-specific decoder.

Solution:

import (
    "image"
    _ "image/png"   // Register PNG decoder
    _ "image/jpeg"  // Register JPEG decoder
    _ "image/gif"   // Register GIF decoder
)

img, format, err := image.Decode(reader)

Prevention: Import the required image format packages using blank imports. The underscore import registers the decoder via init().


Error: error opening profile / error parsing profile

Cause: When using PGO (-pgo flag) or preprofile, the specified CPU profile file is missing, corrupted, or in an unexpected format.

Solution:

# Verify the profile file exists and is valid
go tool pprof default.pgo

# Regenerate the profile
go test -cpuprofile=default.pgo -bench=. ./...

Prevention: Commit the default.pgo file to version control. Re-generate it periodically from production profiles.


Error: globalThis.crypto is not available, polyfill required (WebAssembly)

Cause: Go's WASM runtime requires the Web Crypto API (globalThis.crypto) for random number generation. This is unavailable in some JavaScript environments (older Node.js, web workers without crypto).

Solution:

// Node.js polyfill
const { webcrypto } = require('crypto');
globalThis.crypto = webcrypto;

// Or run Node.js with the flag
// node --experimental-global-webcrypto myapp.js

Error: Go.run: WebAssembly.Instance expected (WebAssembly)

Cause: The Go.run() method received something other than a WebAssembly.Instance. The instantiation step may have failed silently.

Solution:

const go = new Go();
const result = await WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject);
// Pass result.instance, not result
await go.run(result.instance);

Error: total length of command line and environment variables exceeds limit (WebAssembly)

Cause: The WASI or js/wasm environment has a limit on the combined size of command-line arguments and environment variables passed to the Go program.

Solution: Reduce the number or size of environment variables passed to the WASM instance. Use configuration files or other IPC mechanisms instead of environment variables for large values.


Error: Go program has already exited (WebAssembly)

Cause: JavaScript code attempted to call a Go-exported function after the Go program's main() function returned.

Solution: Keep the Go program running by blocking in main():

func main() {
    // Set up exports, event handlers, etc.
    
    // Block forever (for a browser environment)
    select {}
    
    // Or use a channel
    c := make(chan struct{})
    <-c
}

Error: unexpected key value type (Windows registry)

Cause: Reading a Windows registry value that has a different type than expected (e.g., reading a DWORD as a string).

Solution: Use the correct registry.Key method for the value type: GetStringValue(), GetIntegerValue(), GetBinaryValue(), etc. Check the actual type with Stat() first.


Flaky tests on NetBSD (#73820)

Cause: Known intermittent test failures on NetBSD platform, often related to network timing or filesystem behavior differences.

Solution: If building/testing Go itself on NetBSD, retry failed tests individually. These are tracked upstream and are not indicative of real bugs in user code.


Goroutine profile races (#76540)

Cause: Concurrent goroutine profiling can race with goroutine creation/destruction, producing inconsistent profile data.

Solution: Avoid taking goroutine profiles at extremely high frequency. Use the trace tool instead for detailed goroutine analysis.


Timer issues (#67599)

Cause: Edge cases in the runtime timer implementation can cause time.Timer or time.Ticker to behave unexpectedly under high load, particularly around garbage collection of unreferenced timers.

Solution: Always call timer.Stop() when a timer is no longer needed, and drain the channel:

if !timer.Stop() {
    select {
    case <-timer.C:
    default:
    }
}

Tip

Since Go 1.23, stopped time.Timer and time.Ticker channels are automatically drained, simplifying cleanup. On older versions, the drain pattern above is essential to prevent goroutine leaks.


Error: compilation takes too long or uses excessive memory

Cause: Extremely large packages, deeply nested generic instantiations, or complex constant expressions can cause the compiler to consume excessive time and memory.

Solution:

# Limit parallelism to reduce memory usage
go build -p 1 ./...

# Identify the slow package
go build -v ./... 2>&1  # -v shows package names as they compile

# Split large packages into smaller ones

Prevention: Keep packages focused and reasonably sized. Avoid deeply recursive generic types.


Cause: A package references a symbol (via //go:linkname or assembly) that does not exist in any linked package.

Solution: Ensure all required packages are imported (even as blank imports if only their init() side-effects are needed). For assembly files, verify symbol names match exactly.


Error: missing go.sum entry for module providing package XXX

Cause: The go.sum file does not contain a checksum for a required module. This happens when go.sum is out of date relative to go.mod, or when running with -mod=readonly (the default) after adding a new import.

Solution:

# Update go.sum with missing entries
go mod tidy

# Or download and verify the specific module
go mod download

Prevention: Run go mod tidy after adding new imports and commit both go.mod and go.sum.


Error: go: inconsistent vendoring

Cause: The vendor/ directory exists but does not match go.mod. Modules were added or updated in go.mod without re-vendoring.

Solution:

# Re-generate the vendor directory
go mod vendor

# Verify consistency
go mod verify

Prevention: Add go mod vendor to your CI pipeline or pre-commit hooks when using vendoring.


Error: cannot use path@version syntax in GOPATH mode

Cause: Running a module-aware command (like go get pkg@v1.2.3) in a workspace that is not a module (no go.mod).

Solution:

# Initialize a module
go mod init example.com/myproject

# Or ensure GO111MODULE is not set to "off"
go env -u GO111MODULE

Error: cgo: C compiler "gcc" not found: exec: "gcc": executable file not found in $PATH

Cause: CGO is enabled but no C compiler is installed or available in PATH.

Solution:

# Install a C compiler
# Debian/Ubuntu:
sudo apt-get install gcc

# macOS:
xcode-select --install

# Or disable cgo if not needed
CGO_ENABLED=0 go build ./...

Prevention: Set CGO_ENABLED=0 explicitly when building pure Go programs that don't need C interop. This is especially important for cross-compilation and container builds.


Error: cannot load XXX: no Go source files

Cause: The specified package path exists as a directory but contains no .go files (or all .go files are excluded by build constraints).

Solution: Check that the directory contains .go files and that build tags match:

ls path/to/package/*.go
head -3 path/to/package/*.go  # Check //go:build lines

Error: go: updates to go.sum needed, disabled by -mod=readonly

Cause: The default -mod=readonly prevents automatic updates to go.sum. A dependency's checksum is needed but missing.

Solution:

go mod tidy     # Updates both go.mod and go.sum
go mod download  # Downloads and checksums all dependencies

Error: invalid version: module contains a go.mod file, so module path must match major version

Cause: A module at version v2 or higher does not have the major version suffix in its module path. Go modules require example.com/mod/v2 in go.mod for v2.x.x versions.

Solution: This is a module author issue. If you're the author, update the module path in go.mod:

module example.com/mymod/v2

If you're a consumer, import with the versioned path:

import "example.com/mymod/v2/pkg"

Error: found packages foo (foo.go) and bar (bar.go) in /path

Cause: Two .go files in the same directory declare different package names. Go requires all files in a directory to belong to the same package (exception: _test.go files may use package foo_test).

Solution: Ensure all non-test .go files in the directory have the same package declaration. Move files that belong to different packages into separate directories.


11. Quick Reference

Frequently Used Commands

# Build
go build ./...                     # Build all packages
go build -v -race ./cmd/server     # Verbose, with race detector
go build -trimpath -ldflags="-s -w" -o server ./cmd/server  # Production build

# Test
go test ./...                      # Test all packages
go test -v -run TestName ./pkg     # Specific test, verbose
go test -race -count=1 ./...       # With race detector, no cache
go test -bench=. -benchmem ./pkg   # Benchmarks with memory stats
go test -cover -coverprofile=c.out ./...  # Coverage
go tool cover -html=c.out          # View coverage in browser
go test -fuzz FuzzName ./pkg       # Fuzz testing

# Modules
go mod init example.com/proj       # Init module
go mod tidy                        # Clean up go.mod/go.sum
go mod download                    # Pre-download dependencies
go mod vendor                      # Vendor dependencies
go mod verify                      # Check dependency integrity
go get example.com/pkg@v1.2.3     # Add/update dependency
go get -u ./...                    # Update all dependencies

# Diagnostics
go vet ./...                       # Static analysis
go build -gcflags="-m" ./...       # Optimization decisions
GODEBUG=gctrace=1 ./server        # GC tracing
go tool pprof cpu.pprof            # Profile analysis
go tool trace trace.out            # Trace analysis

# Environment
go env                             # Show all env vars
go env -w GOPROXY=https://proxy.corp.com,direct  # Set persistent env
go env -u GOPROXY                  # Unset persistent env
go env GOROOT GOPATH GOCACHE       # Show specific vars

# Workspace
go work init ./mod1 ./mod2         # Init workspace
go work use ./mod3                 # Add module to workspace
go work sync                       # Sync workspace deps

# Maintenance
go clean -cache                    # Clear build cache
go clean -testcache                # Clear test cache
go clean -modcache                 # Clear module cache
go clean -fuzzcache                # Clear fuzz cache
go fix ./...                       # Apply API migrations
go generate ./...                  # Run code generators

Common GODEBUG Settings

Setting Effect
gctrace=1 Print GC statistics each cycle
schedtrace=1000 Print scheduler state every N ms
scheddetail=1 Detailed scheduler info
gcpacertrace=1 GC pacer decisions
scavtrace=1 Memory scavenger activity
allocfreetrace=1 Every allocation and free
inittrace=1 Package init execution times
gocacheverify=1 Verify build cache correctness
gocachehash=1 Log cache hash calculations
gocachetest=1 Log test cache lookups
http2debug=1 HTTP/2 frame logging
http2debug=2 HTTP/2 frame logging + dump
netdns=go Force pure Go DNS resolver
netdns=cgo Force cgo DNS resolver
netdns=1 Debug DNS resolution
x509usefallbackroots=1 Use Go's bundled root certificates
tlsmaxrsasize=8192 Maximum RSA key size in TLS
randautoseed=0 Disable automatic math/rand seeding
asynctimerchan=0 Disable async timer channel behavior

Environment Variable Quick Reference

# Essential for CI/CD
GOOS=linux GOARCH=amd64            # Cross-compilation
CGO_ENABLED=0                       # Pure Go (no cgo)
GOFLAGS=-mod=vendor                 # Use vendored deps
GOTOOLCHAIN=local                   # Pin toolchain version
GOPROXY=https://proxy.golang.org,direct
GONOSUMDB=*.corp.internal
GOPRIVATE=github.com/myorg/*

# Performance tuning
GOGC=100                            # GC target (default 100)
GOMEMLIMIT=2GiB                     # Soft memory limit
GOMAXPROCS=4                        # CPU cores for Go scheduler
GOAMD64=v3                          # AVX2 optimizations

# Debugging
GOTRACEBACK=all                     # Full crash dumps
GODEBUG=gctrace=1                   # GC tracing

GOTRACEBACK Levels

The GOTRACEBACK environment variable controls how much stack trace information is printed on a crash:

Value Behavior
none No goroutine stack traces
single (Default) Stack trace for the crashing goroutine only
all Stack traces for all user-created goroutines
system Stack traces for all goroutines including runtime
crash Like system but also triggers an OS-level crash (core dump)
wer (Windows) Triggers Windows Error Reporting
# Get full goroutine dumps on crash (useful for deadlock debugging)
GOTRACEBACK=all ./server

# Generate core dumps for post-mortem debugging
GOTRACEBACK=crash ./server
# Then analyze with: dlv core ./server core.XXXXX

Go Test JSON Output Format

When running go test -json, each line is a JSON object with this structure:

{
    "Time": "2024-03-15T10:30:00.123Z",
    "Action": "pass",
    "Package": "example.com/mymod/pkg/server",
    "Test": "TestHandleRequest",
    "Output": "--- PASS: TestHandleRequest (0.01s)\n",
    "Elapsed": 0.01
}
Field Description
Time Timestamp (RFC 3339 with nanoseconds)
Action One of: start, run, pause, cont, pass, fail, skip, bench, output
Package Package being tested
Test Test name (absent for package-level events)
Output Text output from the test (only with output action)
Elapsed Duration in seconds (only with pass/fail)

This format is consumed by CI systems, IDEs, and tools like gotestsum for formatted test reporting.

Module Graph Analysis

# Print the full module dependency graph
go mod graph
# Output: module@version dependency@version (one per line)

# Why does a specific module appear in the graph?
go mod why -m golang.org/x/net
# Prints the shortest import chain from the main module

# List all modules with their versions
go list -m all

# List available updates
go list -m -u all

# Show module dependency tree (JSON)
go list -m -json all

# Find which module provides a package
go list -m -json golang.org/x/net/http2

File Extension Reference

Extension Meaning
.go Go source file
_test.go Go test file
.s Go assembly (Plan 9 syntax)
.syso System object file (linked in)
.mod Module definition
.sum Module checksum
.work Workspace definition