Skip to content

CONCEPT Cited by 1 source

Go build tags

Go build tags are file-level compile guards of the form //go:build <expression> (Go 1.17+; older syntax // +build <expression>) that tell the Go compiler whether to include a file in the current build. Build tags are boolean expressions over OS, architecture, Go version, CGO state, and user-defined tags.

Semantics

A file whose build tag evaluates false for the current build:

  • Is excluded from compilation.
  • Does not contribute its imports to the package graph.

This second property is the load-bearing one for binary-size engineering. A compile-excluded file's imports (and their transitive imports) never reach the linker — they don't exist in the binary regardless of DCE behaviour.

Two canonical ways to prune a dep

Per Datadog (2026-02-18), there are exactly two principal ways to keep an unwanted dependency out of a Go binary:

  1. Tag-guard the file that imports it. Mark the file containing the unwanted import with a tag you're not passing (e.g. //go:build unused). The compiler skips the file; the transitive import tree rooted at it is gone. (patterns/build-tag-dependency-isolation)

  2. Move the offending symbol to its own package. Binaries that don't need the symbol simply don't import the new package; its dependencies stay out. (patterns/single-function-forced-package-split)

The first is appropriate when a file contains both architecture-specific / optional code and shared code; the second when a single symbol in an otherwise-shared package is dragging in a costly dep stack.

Invocation

Built-in tags are implicit (GOOS, GOARCH, go1.24, cgo). User tags are passed at build time:

go build -tags "tag1,tag2,!tag3" ./...

Queryable via go list and goda:

GOOS=linux GOARCH=amd64 go list -f '{{ join .Deps "\n" }}' \
    -tags kubernetes,otlp,docker ./cmd/agent

Example: plugin unimport

The fix for the 2026-02-18 Datadog-containerd regression was upstream PR containerd#11203 adding a build tag around the plugin import so downstream consumers (like the Datadog Agent) that don't need user-loadable containerd plugins could build without the tag — and therefore without that import — and see the concepts/go-plugin-dynamic-linking-implication|245 MiB regression disappear.

Seen in

Last updated · 200 distilled / 1,178 read