cheat-sheets

Go and Rust Toolchains

Everyday commands for building, testing and installing programs with the Go toolchain and with Rust’s rustup and cargo. Both compile to single static-ish binaries, which makes them popular for homelab CLIs (several tools in Modern CLI Tools install with cargo install or go install).

Documentation: Go docs, Go command, Rust book, Cargo book

Go: Install and Environment #

COMMANDDESCRIPTION
go versionShow the Go version
go envShow all Go environment settings
go env GOPATH GOROOT GOOS GOARCHShow specific settings
go env -w GOFLAGS=-mod=readonlyPersist a setting
go install golang.org/dl/go1.23.0@latest && go1.23.0 downloadInstall an extra Go version side by side
export PATH="$PATH:$(go env GOPATH)/bin"Put go install binaries on PATH

Download from go.dev/dl or use brew install go (Homebrew) or winget install GoLang.Go (winget). The apt package is often old. Since Go 1.21 the go line in go.mod can trigger an automatic toolchain download (GOTOOLCHAIN).

Go: Modules #

COMMANDDESCRIPTION
go mod init github.com/<USER>/<REPO>Start a module (creates go.mod)
go get <MODULE>@latestAdd or upgrade a dependency
go get <MODULE>@v1.2.3Pin a version
go get -u ./...Update all dependencies of the module
go mod tidyAdd missing and remove unused requirements
go mod downloadFetch dependencies into the module cache
go mod vendorCopy dependencies into vendor/
go mod why <MODULE>Why is it needed
go mod graphDependency graph
go list -m allAll modules in the build
go list -m -u allShow available updates
go clean -modcacheEmpty the module cache

Commit both go.mod and go.sum.

Go: Build, Run, Test #

COMMANDDESCRIPTION
go run .Compile and run the package in the current directory
go build ./...Compile everything (discards results for several packages)
go build -o bin/app ./cmd/appBuild one binary to a path
go build -ldflags "-s -w" -o app .Smaller binary (strip symbols and debug info)
go build -ldflags "-X main.version=1.2.3" .Set a string variable at link time
go build -trimpathRemove local file paths from the binary
go test ./...Run all tests
go test -v -run TestName ./pkgOne test, verbose
go test -race ./...Race detector
go test -cover ./...Coverage summary
go test -coverprofile=c.out ./... && go tool cover -html=c.outHTML coverage report
go test -bench=. -benchmem ./...Benchmarks
go test -count=1 ./...Skip the test result cache
go vet ./...Static checks
gofmt -l -w . / go fmt ./...Format code
go doc <PACKAGE>.<SYMBOL>Show documentation
go tool pprof <FILE>Profile analysis

Go: Install and Cross-Compile #

COMMANDDESCRIPTION
go install <MODULE>/cmd/<TOOL>@latestInstall a tool into $(go env GOPATH)/bin
go install ./cmd/appInstall from the local module
GOOS=linux GOARCH=amd64 go build -o app-linux-amd64 .Cross-compile for Linux x86-64
GOOS=linux GOARCH=arm64 go build -o app-linux-arm64 .Linux ARM64 (Raspberry Pi 4/5, Ampere)
GOOS=windows GOARCH=amd64 go build -o app.exe .Windows
GOOS=darwin GOARCH=arm64 go build -o app-darwin .Apple Silicon
CGO_ENABLED=0 go build -o app .Fully static binary (no C library), ideal for scratch containers
go tool dist listAll supported OS/architecture pairs

PowerShell sets variables differently:

powershell
$env:GOOS = "linux"; $env:GOARCH = "amd64"; go build -o app .
Remove-Item Env:GOOS, Env:GOARCH

A minimal container build pairs well with a multi-stage Dockerfile.

Rust: rustup #

COMMANDDESCRIPTION
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shInstall rustup (review the script first)
winget install Rustlang.RustupWindows (winget)
rustup updateUpdate all toolchains
rustup showActive toolchain and targets
rustup toolchain install stableInstall a channel (beta, nightly, or 1.80.0)
rustup default stableSet the default toolchain
rustup override set nightlyUse a toolchain only in the current directory
rustup component add clippy rustfmtAdd the linter and formatter
rustup component add rust-src rust-analyzerSources and language server for editors (VSCode (Visual Studio Code))
rustup target list --installedInstalled compile targets
rustup target add <TARGET>Add a cross-compile target
rustup self uninstallRemove rustup and Rust
rustc --version / cargo --versionCheck versions

Pin a project toolchain with a rust-toolchain.toml file:

toml
[toolchain]
channel = "stable"
components = ["clippy", "rustfmt"]
targets = ["x86_64-unknown-linux-musl"]

Rust: Cargo #

COMMANDDESCRIPTION
cargo new <NAME>New binary project (--lib for a library)
cargo initInitialise the current directory
cargo add <CRATE>Add a dependency (--features <F>, --dev)
cargo remove <CRATE>Remove a dependency
cargo buildDebug build into target/debug
cargo build --releaseOptimised build into target/release
cargo run -- <ARGS>Build and run, passing arguments to the program
cargo checkType-check without producing binaries (fast)
cargo testRun tests (cargo test <NAME> -- --nocapture for output)
cargo clippy -- -D warningsLint and fail on warnings
cargo fmt / cargo fmt --checkFormat / check formatting
cargo doc --openBuild and open documentation
cargo updateUpdate Cargo.lock within semver ranges
cargo treeDependency tree (-i <CRATE> for reverse)
cargo outdatedOutdated crates (needs cargo install cargo-outdated)
cargo auditKnown vulnerabilities (needs cargo install cargo-audit)
cargo cleanDelete target/
cargo benchRun benchmarks
cargo publishPublish to crates.io

Rust: Install Tools #

COMMANDDESCRIPTION
cargo install <CRATE>Build and install a binary crate into ~/.cargo/bin
cargo install --locked <CRATE>Use the crate’s own lockfile (more reproducible)
cargo install --path .Install the local project
cargo install --git <URL>Install from a Git repository
cargo install --listInstalled crates
cargo uninstall <CRATE>Remove
cargo binstall <CRATE>Download a prebuilt binary instead of compiling (needs cargo-binstall)

Add ~/.cargo/bin to PATH (rustup does this via ~/.cargo/env). Examples: cargo install --locked ripgrep fd-find bat eza zoxide git-delta.

Rust: Release Profile #

toml
# Cargo.toml
[profile.release]
opt-level = 3
lto = true          # slower build, smaller and faster binary
codegen-units = 1
strip = true        # strip symbols
panic = "abort"

Rust: Cross-Compile #

COMMANDDESCRIPTION
rustup target add x86_64-unknown-linux-muslStatic Linux target
cargo build --release --target x86_64-unknown-linux-muslBuild for it (output in target/<TARGET>/release)
rustup target add aarch64-unknown-linux-gnuARM64 Linux (needs gcc-aarch64-linux-gnu and a linker setting)
rustup target add x86_64-pc-windows-gnuWindows from Linux (needs mingw-w64)
cargo install crosscross build --target <TARGET> uses Docker containers with the right toolchain (Docker)
cargo zigbuild --target <TARGET>Use Zig as the linker (needs cargo-zigbuild)

Set a linker for a target in .cargo/config.toml:

toml
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"

Pure-Rust projects cross-compile easily; crates that need C libraries (OpenSSL) are the usual problem. Prefer rustls features, or use cross.

Go vs Rust Quick Map #

TASKGORUST
New projectgo mod initcargo new
Add dependencygo get <MOD>cargo add <CRATE>
Build / rungo build / go run .cargo build / cargo run
Testgo test ./...cargo test
Format / lintgo fmt / go vetcargo fmt / cargo clippy
Install a toolgo install <MOD>@latestcargo install <CRATE>
Dependency filego.mod, go.sumCargo.toml, Cargo.lock

Not Verified #

Commands were written from the official documentation and not executed. Crate names and cross-compile linker packages depend on the target distro.

Search all sheets

Tip: / or Ctrl/Cmd+K to open, Esc to close.