CONCEPT Cited by 1 source
reflect.MethodByName linker pessimism¶
reflect.MethodByName(name) with a non-constant name is
the single Go language feature that most aggressively defeats the
linker's
method dead-code elimination.
Mechanism¶
When a Go program calls v.MethodByName(name) and name is a
compile-time constant, the linker can trace exactly which method
is invoked and include only that one. When name is dynamic — the
normal use case — the linker can't know at build time which method
will be resolved. Safe behaviour: keep every exported method of
every reachable type, plus every symbol those methods
transitively depend on.
This can balloon binary size dramatically — Datadog measured 16-25 % per binary when method-DCE was blocked, and the savings recovered when they fixed every offender.
Canonical stdlib offenders¶
text/template and
html/template are the primary
real-world sources: their execution engine calls
reflect.MethodByName with the method name parsed from the
template body at runtime ({{ .Error }} → call .Error() on
the piped value). Any binary importing either one (directly or
transitively) loses method-DCE across the entire reachable type
graph.
Diagnosis¶
go build -ldflags=-dumpdep prints why each symbol is reachable;
whydeadcode consumes that output and names
the first call chain that disabled method-DCE. Only the first
entry is guaranteed correct — iterate (fix, re-run) until the
output is empty.
Workarounds¶
- Patch the site. Replace dynamic
MethodByNamewith exhaustive switch / interface dispatch where feasible. - Build-tag-guard. If the dynamic path is optional, put it behind a build tag (patterns/build-tag-dependency-isolation).
- Package-split. Move the dynamic surface to a separate package that only binaries needing it import (patterns/single-function-forced-package-split).
- Fork stdlib. Datadog's last-resort move for
text/template+html/template: fork intopkg/template/with method-call path statically disabled. Maintenance burden, but the only option while the upstream Go issue #72895 is unresolved.
Datadog's upstream patches¶
The 2026-02-18 post lists PRs to ~a dozen dependencies, e.g.:
Canonical patterns/upstream-the-fix datum: Kubernetes itself subsequently enabled method-DCE and reports 16-37 % of its own.
Seen in¶
- sources/2026-02-18-datadog-how-we-reduced-agent-go-binaries-up-to-77-percent
— 16-25 % per binary / ~100 MiB total Linux
amd64wins once every offender was patched.