跪拜 Guibai
← All articles
Go

Google Wire Is Dead and Uber Fx Panics at Boot — A Compile-Time DI Library Steps In

By 程序员老鹰 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Dependency injection in Go has been split between compile-time safety that's painful to use and runtime convenience that fails in production. A library that delivers both — and whose generated code doesn't tether you to a framework — removes the trade-off entirely.

Summary

Google Wire's compile-time dependency injection came with three persistent headaches: mandatory `return nil, nil` dummy statements, no startup hooks, and zero generics support. Uber Fx swaps those for a clean API but relies on runtime reflection, so missing dependencies and type mismatches only surface as panics when the binary starts — a time bomb that gets worse as projects grow. A new library, dig, generates pure Go code at compile time with no reflection overhead, supports native generics, provides built-in Invoke hooks, and catches closure capture mistakes that Wire silently ignores. Its API mirrors Fx closely enough that migration takes minutes, and the generated output carries no runtime dependency on dig itself.

Takeaways
Google officially archived Wire in August 2025; it still works but will receive no new features.
Wire requires a `return nil, nil` dummy statement because `wire.Build` is a compile-time marker that never executes.
Wire provides no startup hooks, forcing developers to manually maintain an initialization checklist in `main.go`.
Wire does not support Go generics natively; every generic type needs a hand-written wrapper function.
Uber Fx resolves dependencies at runtime via reflection, so missing providers or type mismatches cause startup panics, not compile errors.
Fx startup time grows with project size because the entire dependency tree is re-parsed on every launch.
dig is a compile-time code-generation DI library with an API similar to Fx but no runtime reflection.
dig supports native Go generics, built-in Invoke hooks, and catches illegal closure captures during code generation.
dig's generated code is pure Go with no runtime dependency on the dig library itself.
Migrating from Fx to dig takes roughly five minutes because the APIs are nearly identical.
Conclusions

Wire's `return nil, nil` pattern is a symptom of treating code generation as a side effect rather than a first-class output; dig eliminates it by returning a real function from `Build`.

Runtime DI frameworks shift failure from the compiler to the deploy, which is the worst possible moment to discover a missing dependency.

Compile-time code generation that produces plain Go functions sidesteps both the reflection tax and the lock-in of a runtime container.

Closure capture mistakes are a subtle class of bug that Wire ignores entirely; catching them at generation time prevents silent miscompilation.

The Go community's tolerance for `return nil, nil` for years suggests a willingness to accept awkward tooling when the alternative (runtime panics) feels worse.

Concepts & terms
Compile-time dependency injection
A DI approach where the dependency graph is resolved and code is generated during `go generate`, so the final binary contains only plain function calls with no reflection or runtime container.
Runtime reflection DI
A DI approach (used by Uber Fx) that inspects provider function signatures at program startup using Go's reflect package, building the dependency graph in memory each time the binary runs.
Invoke
A DI hook that executes a function automatically once all its dependencies are satisfied, commonly used for startup tasks like health checks, route registration, or cache warming.
Closure capture
When an inline function references a variable from its enclosing scope. In DI provider functions, accidental captures can produce invalid generated code that compiles incorrectly or not at all.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗