Open-Source Wikis

/

Go

/

Go

/

Architecture

golang/go

Architecture

The Go distribution is a self-contained toolchain. A user-invoked go command drives a small set of cooperating tools (compile, asm, link, cgo, vet) that together turn .go source into an executable. The executable embeds the Go runtime, which manages goroutines, memory, and garbage collection at runtime.

Repository layout at a glance

go/
├── src/
│   ├── cmd/          # All command-line tools: go, compile, link, asm, vet, gofmt, cgo, ...
│   │   ├── compile/  # The gc compiler (frontend, IR, SSA, codegen)
│   │   ├── go/       # The user-facing 'go' command (build, test, get, mod, ...)
│   │   ├── link/     # The linker
│   │   ├── asm/      # The assembler
│   │   ├── cgo/      # The cgo preprocessor
│   │   ├── gofmt/    # The formatter
│   │   ├── vet/      # The static analyzer
│   │   └── internal/ # Shared compiler/linker internals (obj, objabi, ...)
│   ├── runtime/      # Goroutine scheduler, GC, allocator, panic, defer, channels
│   ├── internal/     # Stdlib-internal packages (not importable by users)
│   ├── crypto/ net/ encoding/ fmt/ io/ os/ ...   # The public standard library
│   └── vendor/       # Vendored dependencies for the standard library
├── doc/              # Specification (go_spec.html), memory model, godebug, release notes
├── api/              # Declared public API of every Go release (drives 'go api' check)
├── test/             # End-to-end compiler/runtime regression tests
├── lib/              # Time zone data, Wasm support files
├── misc/             # Miscellaneous: cgo demos, Wasm exec scripts, editor configs
└── src/make.bash     # Build script that bootstraps the toolchain

How a Go program is built

A typical go build invocation drives this pipeline:

graph LR
    User[User: go build] --> GoCmd[cmd/go: go command]
    GoCmd -->|resolve modules,<br/>load packages| Load[modload + load]
    Load -->|per-package| Compile[cmd/compile: gc]
    Compile -->|object .a| Link[cmd/link: linker]
    Asm[cmd/asm: assembler] -->|object .o| Link
    Cgo[cmd/cgo: preprocess C] --> Compile
    Link -->|executable| Binary[(Go binary)]
    Binary -->|embeds| Runtime[runtime: scheduler + GC]
  • cmd/go is the orchestrator. It parses flags, resolves module versions, walks the import graph, schedules per-package builds, manages the build cache, and shells out to compile, asm, link, and cgo.
  • cmd/compile (the "gc" compiler) turns a single Go package's source into an object archive plus export data. See src/cmd/compile/README.md for the seven-phase pipeline (parse → typecheck → noder → middle end → walk → SSA → machine code).
  • cmd/asm turns Go's pseudo-assembly (.s) files into objects on the target architecture.
  • cmd/cgo runs before cmd/compile for packages that import "C", generating the bridge code between Go and C.
  • cmd/link produces the final executable from all object files plus runtime support and metadata.

How a Go program runs

Every Go binary embeds runtime from src/runtime/. The runtime starts before main.main and provides the abstractions that make Go feel high-level:

graph TD
    Entry[rt0_*: arch entry stub] --> Bootstrap[runtime.rt0_go]
    Bootstrap --> Schedinit[schedinit]
    Schedinit --> Mainstart[runtime.main]
    Mainstart --> UserMain[user main.main]
    Mainstart -.spawns.-> GC[GC worker goroutines]
    Mainstart -.spawns.-> Sysmon[sysmon: monitoring thread]
    UserMain -.uses.-> Scheduler[G-M-P scheduler]
    Scheduler --> OS[OS threads via clone/pthread/CreateThread]
    UserMain -.allocates via.-> Mheap[mheap + mcache]
    Mheap --> GC

The runtime's three core abstractions, documented in src/runtime/HACKING.md:

  • G — a goroutine. Cheap to create. A G has a small growable stack (starts ~2 KiB).
  • M — an OS thread. Created on demand. Up to GOMAXPROCS Ms run user Go code at any time; more Ms exist when goroutines are blocked in syscalls.
  • P — a "processor." A scheduling context with a local run queue. Exactly GOMAXPROCS Ps exist. To run user Go code, an M must hold a P.

When user Go code calls a library, that library code is just normal Go that runs on the same goroutine. The runtime is only entered for special operations: allocation, channel send/receive, syscalls, go statements, panics, defers, and growable stack splits.

Where the standard library fits

Standard library packages (fmt, net/http, crypto/*, etc.) live alongside the runtime under src/. They are normal Go packages with one important quirk: they are compiled as part of the same toolchain build that produces them, and their object files are cached in $GOROOT/pkg. Users get them implicitly with every Go installation.

A few standard library packages are tightly coupled to the runtime:

  • sync, sync/atomic — primitives implemented partly in the runtime via //go:linkname.
  • reflect — uses runtime type metadata directly.
  • runtime/pprof, runtime/trace — public APIs over runtime instrumentation.
  • os, syscall — the OS abstraction layer; the runtime calls into syscall for some operations.

The bootstrap loop

The Go toolchain is self-hosted. Building Go requires a working Go compiler. src/make.bash resolves this by:

  1. Locating a "bootstrap" Go (set via GOROOT_BOOTSTRAP, default ~/go1.4 or ~/sdk/go1.22.6).
  2. Using the bootstrap toolchain to build cmd/dist, the build coordinator.
  3. cmd/dist then builds the new compiler, linker, and assembler with the bootstrap.
  4. The new toolchain rebuilds itself once or twice for stability and to pick up its own optimizations.
  5. Finally, the new toolchain builds the standard library and the rest of the commands.

See Getting started and How to contribute → development workflow for the developer-facing version of this loop.

What is intentionally missing

Several things are not in this repository even though they are part of the Go ecosystem:

  • The golang.org/x/* repositories (tools like gopls, goimports, dlv, staticcheck) — these live in separate modules.
  • The Go playground, Go website, and module proxy infrastructure — all separate repos.
  • Third-party compilers like gccgo (in GCC) and tinygo.
  • Build infrastructure (golang.org/x/build) that drives the trybots and release process.

For a complete tour of internal subsystems, see Components.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Architecture – Go wiki | Factory