Lesson 01 of 9 · Part 1 — The language
Why Go for platform work: toolchain, modules and layout
Why so much infrastructure is written in Go, how to install it, and the handful of commands you use every day: modules, run, build, test, vet and fmt, plus a project layout that stays simple.
Why Go shows up everywhere in infrastructure
Kubernetes, Docker, containerd, Terraform, Prometheus, Grafana's backend, etcd, Argo CD, Cilium, Helm: all Go. The reasons matter for the tools you write too:
| Property | What it means for a platform engineer |
|---|---|
| Single static binary | Copy one file to a node, a container or an air-gapped site; no interpreter, no pip install |
| Fast start, low memory | CLIs feel instant; controllers and agents stay small |
| Concurrency built in | Talk to 500 clusters or nodes at once with goroutines |
| Strong standard library | HTTP, JSON, TLS, crypto, templates, testing without dependencies |
| Easy cross-compilation | Build Linux ARM64 binaries from a Mac with one environment variable |
| The Kubernetes ecosystem | client-go, controller-runtime and Kubebuilder are Go-first |
Bash is a pocket knife: always with you, great for small jobs. Python is a toolbox: lots of tools, but you need to carry the box (interpreter and packages). Go is a power tool you can hand to anyone: one solid piece that works the same everywhere.
When to keep Bash or Python: glue scripts of a few lines (Bash), data wrangling and notebooks (Python). Reach for Go when a tool is shared, long-lived, needs to be fast or concurrent, or must run where you can't install anything.
Install and check
Download from go.dev (or brew install go, or your distribution's package, which may be older). Then:
$ go version
go version go1.26.0 linux/amd64
$ go env GOPATH
/home/me/go
Your first module
$ mkdir kaudit && cd kaudit
$ go mod init github.com/me/kaudit
package main
import (
"fmt"
"os"
)
func main() {
host, err := os.Hostname()
if err != nil {
fmt.Fprintln(os.Stderr, "error:", err)
os.Exit(1)
}
fmt.Printf("hello from %s\n", host)
}
$ go run .
hello from laptop
$ go build -o bin/kaudit . && ./bin/kaudit
Every Go file starts with package; main with a main() function makes a program. Imports are package paths; unused imports and variables are compile errors, which keeps code tidy.
The tools you use every day
gofmtformats code (there is one style; your editor runs it on save).go vetfinds suspicious code (wrong printf verbs, copied locks).go testruns tests (lesson 09).go mod tidykeepsgo.modandgo.sumin step with your imports. Commit both files.
A layout that stays simple
kaudit/
├── go.mod, go.sum
├── main.go # or cmd/kaudit/main.go when there are several binaries
├── internal/audit/ # your packages; "internal" can't be imported by other modules
│ ├── audit.go
│ └── audit_test.go
└── Dockerfile
Start with one package; split when a file grows past a few hundred lines or a clear boundary appears. Don't copy large "standard layouts" for small tools.
Try it: one binary, three platforms
- Install Go and create the module above.
- Add a
versionvariable and print it; build with-ldflags "-X main.version=0.1.0". - Cross-compile for
linux/amd64,linux/arm64anddarwin/arm64withGOOS/GOARCH, and check each withfile. - Copy the Linux binary into an
alpinecontainer and run it (build withCGO_ENABLED=0first). - Run
go vetandgofmt -l .; add an unused import and read the compile error.
Going deeper: dependencies
- Prefer the standard library for HTTP, JSON, flags and logging; add dependencies when they save real work (cobra, client-go).
- Use
go list -m allto see the full dependency tree andgovulncheck ./...to check it for known vulnerabilities. - Use workspaces (
go work) only when developing several modules together.
Recap
- Go suits infrastructure: static binaries, fast start, concurrency, a strong standard library, easy cross-compilation.
- A module (
go.mod) is your project;go run,build,test,vet,fmt,mod tidyare the daily commands. - Keep the layout small:
main.goplusinternal/packages.
This site is a public version of my personal engineering knowledge hub. It intentionally excludes confidential company information and internal operational details.