11. Tooling & Delivery

Ship reproducible builds, run strong linters, fuzz critical parsers, and optimize images for security.

Question: What is your preferred tool for linting, and why is it important?

Answer: My preferred tool is golangci-lint. It's a fast and configurable aggregator that runs dozens of different linters in parallel. Linting is crucial for maintaining code quality, enforcing team-wide style conventions, and catching common bugs and performance issues before they are even committed.

Explanation: A strict, shared golangci-lint configuration in CI/CD is a high-leverage way to improve a codebase. It automates code reviews for common issues, allowing human reviewers to focus on higher-level architectural and logic concerns. It can catch everything from errcheck violations (ignoring an error) to subtle performance issues like unnecessary string-to-byte conversions.

Question: How do you use fuzz testing effectively in Go?

Answer: Write FuzzXxx functions to exercise APIs with randomized inputs, add seeds for edge cases, and run in CI for critical parsers and validators.

Explanation: Fuzzing (Go 1.18+) finds panics and logic errors beyond hand-written unit tests. Keep fuzzers deterministic by capping time and minimizing global state.

Question: What are the key characteristics of a good Dockerfile for a Go application?

Answer: A good Dockerfile for Go uses a multi-stage build. The first stage (the "builder") uses a full Go SDK image to build a statically-linked binary. The second, final stage copies only that binary into a minimal scratch or distroless base image. This produces a tiny, secure image with a minimal attack surface.

Explanation: A static, distroless image contains only your application and its direct dependencies, with no shell, package manager, or other unnecessary programs. This is a major security win. The Dockerfile should also run the application as a non-root user and explicitly set USER.

# Example of building with version injection
CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -buildid= -X main.version=$(git describe --always --dirty) -X main.buildDate=$(date -u +%FT%TZ)"

Question: How do you ensure reproducible builds and provenance?

Answer: Pin toolchains, use -trimpath, avoid dynamic data in binaries, generate SBOMs, and sign artifacts (cosign/slsa provenance).

Explanation: Reproducibility enables verifiable supply chains and rollbacks; provenance attests who built what, when, and with which inputs.

Question: How do you set up a build process for cross-compilation, and how do build tags work?

Answer: Cross-compilation in Go is straightforward by setting the GOOS (target operating system) and GOARCH (target architecture) environment variables before running go build. Build tags (or build constraints) are line comments placed at the top of a Go file that control whether the file is included in a build.

Explanation:

  • Cross-compilation: To build a Linux binary on a Mac, you would run GOOS=linux GOARCH=amd64 go build -o my-app-linux .. This first-class support is a major advantage of Go's toolchain.

  • Build Tags: A comment like //go:build linux at the top of a file ensures it's only compiled when GOOS=linux. You can combine tags with && and ||. This is the standard way to handle platform-specific implementations of an interface, allowing you to write clean, platform-agnostic business logic that relies on an interface, with separate files providing the OS-specific implementation.

Question: How can you bundle static assets and migrations without external dependencies?

Answer: Use the embed package to compile files into the binary and access them via embed.FS.

Explanation: Embedding simplifies deployment and eliminates runtime file path issues; ideal for web assets and SQL migrations.

import "embed"

//go:embed static/* migrations/*.sql
var content embed.FS

Question: How do you produce and ship reproducible releases?

Answer: Use goreleaser with pinned toolchains, -trimpath, injected versions, and SBOM/signing (e.g., cosign). Avoid non-deterministic steps.

Explanation: Reproducibility improves supply-chain integrity and rollback confidence.