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 whenGOOS=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.