Go DI has always been a trade-off.
Runtime DI frameworks provide a convenient API, but they rely on reflection and discover dependency problems during application startup.
Compile-time DI frameworks avoid those problems, but some APIs become verbose and less ergonomic.
I have been exploring a different approach:
dig — compile-time dependency injection for Go with an Fx-style API and Wire-style code generation.
Repository:
https://github.com/shanjunmei/dig
The main design goals are:
dependency graph resolution during go generate
zero runtime reflection
zero runtime dependency after code generation
generated code is plain Go
minimal API: dig.Build, dig.Provide, dig.Supply, dig.Invoke, dig.Module
Example:
func InitApp() func(context.Context) error {
return dig.Build(
dig.Provide(NewConfig),
dig.Provide(NewDatabase),
dig.Invoke(StartServer),
)
}
After generation, the application does not depend on a DI runtime.
Some design questions I would like feedback on:
Do you prefer compile-time DI or runtime DI in large Go projects?
Is avoiding reflection an important advantage in practice?
Are there DI patterns from Wire/Fx/custom solutions that should be preserved?
What API choices would make a Go DI library feel natural?
The goal is not to create another DI library for its own sake, but to explore what a more Go-like DI design could look like.
Feedback and criticism are welcome.