✌️ Dependency Injection in Go
Dependency injection (DI) in Go is the practice of supplying a component with the services it depends on, instead of letting it construct them itself — making code easier to test, swap, and reason about. samber/do is a DI toolkit for Go that implements this pattern using 1.18+ generics instead of reflection, giving you a type-safe API with no code generation and zero external dependencies.
See also:
- samber/lo: A Lodash-style Go library based on Go 1.18+ Generics
- samber/mo: Monads based on Go 1.18+ Generics (Option, Result, Either...)
Why this name?
I love the short name for such a utility library. This name is the sum of DI and Go and no Go package uses this name.
samber/do vs uber/dig vs uber/fx vs google/wire
samber/do | uber/dig | uber/fx | google/wire | Manual DI | |
|---|---|---|---|---|---|
| Mechanism | Generics | Reflection | Reflection (built on dig) | Code generation | Hand-written |
| Type safety | Compile-time | Runtime | Runtime | Compile-time | Compile-time |
| Code generation | None | None | None | Required (wire CLI) | None |
| Lifecycle management | Health checks, graceful shutdown, hooks | None built-in | Start/stop hooks | None | Hand-written |
| Scopes / modules | Full scope tree | Limited | Modules | Provider sets | Hand-written |
| Debugging tools | Scope tree, dependency graph, Web UI | None built-in | fx.WithLogger | None (inspect generated code) | N/A |
| External dependencies | None | None | Several (dig, zap, ...) | wire build tool | None |
When to use samber/do: you want compile-time-checked service resolution without a build step, plus built-in health checks and graceful shutdown for production services. See the detailed comparisons: do vs uber/fx, do vs google/wire, and do vs uber/dig. Already using one of these? Check the migration guides.
💡 Features
samber/do is built with high attention to the developer and contributor experience.
- 📒 Service registration
- Register by type
- Register by name
- Register multiple services from a package at once
- 🪃 Service invocation
- Eager loading
- Lazy loading
- Transient loading
- Tag-based invocation
- Circular dependency detection
- 🧙♂️ Service aliasing
- Implicit (provide struct, invoke interface)
- Explicit (provide struct, bind interface, invoke interface)
- 🔁 Service lifecycle
- Health check
- Graceful unload (shutdown)
- Dependency-aware parallel shutdown
- Lifecycle hooks
- 📦 Scope (a.k.a. module) tree
- Visibility control
- Dependency grouping
- 📤 Container
- Dependency graph resolution and visualization
- Default container
- Container cloning
- Service override
- 🧪 Debugging & introspection
- Explain APIs: scope tree and service dependencies
- Web UI & HTTP middleware (std, Gin, Fiber, Echo, Chi)
- 🌈 Lightweight, no dependencies
- 🔅 No code generation
- 😷 Type‑safe API
Where to go next
- New to
samber/do? Start with Getting started. - Coming from another DI library? Read the migration guides or the comparison pages.
- Have a specific question? Check the FAQ or the glossary.
- Upgrading from v1? See the v1 to v2 upgrade guide.