A lightweight, type-safe DI container for Go. Leverage generics for compile-time safety with a clean, intuitive API.
container := di.New()
// Register with auto-resolved dependencies
di.Register[UserService](container,
func(db Database, log Logger) UserService {
return &DefaultUserService{db, log}
},
di.AsSingleton(),
)
// Resolve — all dependencies injected!
service := di.MustResolve[UserService](container)
Compile-time type checking with Register[T]() and Resolve[T](). No runtime type assertions.
Transient, Singleton, or Scoped. Control exactly how long your dependencies live and when they're created.
Factory parameters are automatically resolved. Just declare what you need and let the container handle wiring.
Automatically detects circular dependencies and fails fast with clear, actionable error messages.
Register multiple implementations of the same interface with names. Perfect for strategy patterns.
Fully concurrent. Register and resolve from multiple goroutines without worry.
Up and running in under a minute
go get github.com/pegasusheavy/go-dependency-injector
import "github.com/pegasusheavy/go-dependency-injector/di"
container := di.New()
// Register a singleton logger
di.Register[Logger](container, func() Logger {
return &ConsoleLogger{}
}, di.AsSingleton())
// Register with auto-resolved dependencies
di.Register[UserService](container, func(log Logger) UserService {
return &DefaultUserService{logger: log}
})
// Resolve with error handling
service, err := di.Resolve[UserService](container)
if err != nil {
log.Fatal(err)
}
// Or use MustResolve for known registrations
service := di.MustResolve[UserService](container)
service.DoSomething()
Everything at a glance
Register[T](c, factory, opts...)
Register with factory function
RegisterInstance[T](c, instance)
Register existing instance
RegisterType[I, T](c, opts...)
Register interface → implementation
Resolve[T](c) → (T, error)
Resolve with error handling
MustResolve[T](c) → T
Resolve or panic
ResolveNamed[T](c, name) → (T, error)
Resolve named registration
ResolveInScope[T](c, scope) → (T, error)
Resolve within a scope
Transient
New instance every resolution (default)
Singleton
Single shared instance
Scoped
One instance per scope
AsSingleton()
AsTransient()
AsScoped()
WithName("name")