Cheat Sheets / Linux, Scripting & Go

Go for Infrastructure Engineers cheat sheet

59 commands from every lesson of Go for Infrastructure Engineers, on one page.

01 · Why Go for platform work: toolchain, modules and layout

Every day

go mod init github.com/me/kauditStart a module (the import path of your project)
go run .Compile and run the package in this folder
go build -o bin/kaudit .Build a binary
go test ./...Run all tests in the module
go vet ./... && gofmt -l .Static checks and unformatted files
go get k8s.io/client-go@v0.34.0Add or change a dependency version
go mod tidyAdd missing and remove unused dependencies

Build for elsewhere

CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o kaudit-arm64 .Static Linux binary for ARM64, from any machine
go build -ldflags='-s -w -X main.version=1.2.0' .Smaller binary, version stamped at build time
go env GOPATH GOCACHEWhere modules and build cache live

02 · Go through Bash and Python eyes

Syntax at a glance

x := 3Declare and assign (type inferred) inside functions
var nodes []stringDeclare with the zero value (nil slice, ready to append)
nodes = append(nodes, "n1")Add to a slice
counts := map[string]int{}Empty map ready to use
for i, n := range nodes { }Loop over a slice with index and value
if v, ok := counts["n1"]; ok { }Read a map key and check it exists
type Node struct { Name string; Ready bool }Define a struct
func (n Node) String() string { }A method on a type

03 · Errors done right

Patterns

if err != nil { return fmt.Errorf("read %s: %w", path, err) }Add context and keep the original error
if errors.Is(err, os.ErrNotExist) { }Is it (or does it wrap) this specific error?
var nf *NotFoundError; if errors.As(err, &nf) { }Is it (or does it wrap) this error type? Get it
defer f.Close()Run clean-up when the function returns, whatever path it takes
var ErrNoNodes = errors.New("no nodes")A sentinel error callers can test for

04 · Building command-line tools

Building blocks

flag.String("cluster", "", "cluster name")Standard-library flag
go get github.com/spf13/cobra@latestAdd cobra for subcommands
slog.New(slog.NewJSONHandler(os.Stderr, nil))Structured JSON logs to stderr
signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM)A context cancelled on Ctrl-C or SIGTERM
os.Exit(2)Exit with a specific code (deferred calls don't run!)

05 · HTTP, JSON and APIs

Patterns

client := &http.Client{Timeout: 10 * time.Second}Never use a client without a timeout
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)Request that stops when ctx is cancelled
defer resp.Body.Close()Always close bodies (connection reuse)
json.NewDecoder(resp.Body).Decode(&out)Decode JSON straight from the response
if resp.StatusCode >= 300 { }Errors from the server are not Go errors: check the status

06 · Concurrency you'll actually use

Patterns

var wg sync.WaitGroup; wg.Add(1); go func() { defer wg.Done() }()Start work and wait for it
g, ctx := errgroup.WithContext(ctx); g.SetLimit(10)Run tasks, at most 10 at once, cancel all on first error
select { case v := <-ch: case <-ctx.Done(): }Wait for whichever happens first
var mu sync.Mutex; mu.Lock(); defer mu.Unlock()Protect shared state
go test -race ./... / go run -race .Detect data races

07 · client-go: talking to Kubernetes

Set-up

go get k8s.io/client-go@v0.34.0 k8s.io/apimachinery@v0.34.0client-go and apimachinery, versions matching your clusters' minor
clientcmd.BuildConfigFromFlags("", kubeconfigPath)Config from a kubeconfig file
rest.InClusterConfig()Config inside a pod (ServiceAccount token)
kubernetes.NewForConfig(cfg)The typed clientset

Calls

cs.CoreV1().Nodes().List(ctx, metav1.ListOptions{})List nodes
cs.CoreV1().Pods("").List(ctx, metav1.ListOptions{FieldSelector: "status.phase=Pending"})Pending pods in all namespaces
cs.CoreV1().Nodes().Patch(ctx, name, types.MergePatchType, data, metav1.PatchOptions{})Patch a node (labels, annotations)
apierrors.IsNotFound(err)Was it a 404?

08 · A small controller with Kubebuilder

Kubebuilder

kubebuilder init --domain platform.example.com --repo github.com/me/team-operatorScaffold a project
kubebuilder create api --group platform --version v1alpha1 --kind TeamNamespaceA CRD type and its controller
make manifests generateRegenerate CRD YAML, RBAC and deep-copy code after editing types
make install runInstall the CRD into the current cluster and run the controller locally
make testUnit and envtest-based tests
make docker-build deploy IMG=registry.example.com/team-operator:0.1.0Build and deploy into the cluster

09 · Testing, linting and shipping

Quality

go test ./... -race -coverAll tests, race detector, coverage
go test -run TestParse/empty -v ./internal/auditOne sub-test, verbose
golangci-lint runMany linters at once (errcheck, staticcheck, govet…)
govulncheck ./...Known vulnerabilities in code paths you actually call

Ship

CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' -o kaudit .Small static binary
docker build -t registry.example.com/kaudit:0.1.0 .Multi-stage build into a distroless image
goreleaser release --cleanMulti-platform binaries, checksums and release notes from a tag