skills/golang-samber-do/SKILL.md
Dependency injection in Golang using samber/do — service containers, lifecycle management, scopes, health checks, graceful shutdown, and module organization. Apply when using or adopting samber/do, when the codebase imports github.com/samber/do or github.com/samber/do/v2, or when refactoring manual constructor injection into a DI container.
npx skillsauth add samber/cc-skills-golang golang-samber-doInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Persona: You are a Go architect setting up dependency injection. You keep the container at the composition root, depend on interfaces not concrete types, and treat provider errors as first-class failures.
Type-safe dependency injection toolkit for Go based on Go 1.18+ generics.
Official Resources:
This skill is not exhaustive. Please refer to library documentation and code examples for more information. Context7 can help as a discoverability platform.
DO NOT USE v1 OF THIS LIBRARY. INSTALL v2 INSTEAD:
go get -u github.com/samber/do/v2
import "github.com/samber/do/v2"
injector := do.New()
Services MUST be registered via provider functions:
type Provider[T any] func(i Injector) (T, error)
Follow "Accept Interfaces, Return Structs":
// Register a service (lazy by default)
do.Provide(injector, func(i do.Injector) (Database, error) {
return &PostgreSQLDatabase{connString: "postgres://..."}, nil
})
// Register a pre-created value
do.ProvideValue(injector, &Config{Port: 8080})
// Register a transient service (new instance each time)
do.ProvideTransient(injector, func(i do.Injector) (*Logger, error) {
return &Logger{}, nil
})
// Register an eager service (created immediately at startup)
do.ProvideValue(injector, &Config{Port: 8080})
The container MUST only be accessed at the composition root:
// Invoke with error handling
db, err := do.Invoke[Database](injector)
// MustInvoke panics on error (use when confident service exists)
db := do.MustInvoke[Database](injector)
func NewUserService(i do.Injector) (UserService, error) {
db := do.MustInvoke[Database](i)
cache := do.MustInvoke[Cache](i)
return &userService{db: db, cache: cache}, nil
}
do.Provide(injector, NewUserService)
Register a concrete type and invoke as an interface without explicit aliasing:
// Register concrete type
do.Provide(injector, func(i do.Injector) (*PostgreSQLDatabase, error) {
return &PostgreSQLDatabase{}, nil
})
// Invoke directly as interface (implicit aliasing)
db := do.MustInvokeAs[Database](injector)
Register multiple services of the same type:
do.ProvideNamed(injector, "primary-db", func(i do.Injector) (*Database, error) {
return &Database{URL: "postgres://primary..."}, nil
})
mainDB := do.MustInvokeNamed[*Database](injector, "primary-db")
Use do.Package() to organize service registration by module:
// infrastructure/package.go
var Package = do.Package(
do.Lazy(func(i do.Injector) (*postgres.DB, error) {
cfg := do.MustInvoke[*Config](i)
return postgres.Connect(cfg.DatabaseURL)
}),
do.Lazy(func(i do.Injector) (*redis.Client, error) {
cfg := do.MustInvoke[*Config](i)
return redis.NewClient(cfg.RedisURL), nil
}),
)
// main.go
injector := do.New(infrastructure.Package, service.Package)
func main() {
injector := do.New(
infrastructure.Package,
repository.Package,
service.Package,
transport.Package,
)
server := do.MustInvoke[*http.Server](injector)
go server.ListenAndServe()
_ = injector.ShutdownOnSignalsWithContext(context.Background(), os.Interrupt)
}
For scopes, lifecycle management, struct injection, and debugging, see Advanced Usage.
For testing patterns (cloning, overrides, mocks), see Testing.
| Function | Purpose |
| ------------------------------- | -------------------------------- |
| do.Provide[T]() | Register lazy service (default) |
| do.ProvideNamed[T]() | Register named lazy service |
| do.ProvideValue[T]() | Register pre-created value |
| do.ProvideNamedValue[T]() | Register named value |
| do.ProvideTransient[T]() | Register new instance each time |
| do.ProvideNamedTransient[T]() | Register named transient service |
| do.Package() | Group service registrations |
| Function | Purpose |
| -------------------------- | ----------------------------------------- |
| do.Invoke[T]() | Get service (with error) |
| do.InvokeNamed[T]() | Get named service |
| do.InvokeAs[T]() | Get first service matching interface |
| do.InvokeStruct[T]() | Inject into struct fields using tags |
| do.MustInvoke[T]() | Get service (panic on error) |
| do.MustInvokeNamed[T]() | Get named service (panic on error) |
| do.MustInvokeAs[T]() | Get service by interface (panic on error) |
| do.MustInvokeStruct[T]() | Inject into struct (panic on error) |
samber/cc-skills-golang@golang-dependency-injection skill for DI concepts, comparison, and when to adopt a DI librarysamber/cc-skills-golang@golang-structs-interfaces skill for interface design patternssamber/cc-skills-golang@golang-testing skill for general testing patternsdevelopment
Golang skills orchestrator — always active on any Golang coding, review, debug, or setup task. Reads the task context and loads the most relevant skills from samber/cc-skills-golang, often multiple at once: writing a gRPC service loads golang-grpc + golang-testing + golang-error-handling; debugging a panic loads golang-troubleshooting + golang-safety; auditing security loads golang-security + golang-lint + golang-safety. Also: disambiguates competing clusters when two skills seem to overlap (performance vs benchmark vs troubleshooting, samber/lo vs mo vs ro, DI cluster, safety vs security), and configures CLAUDE.md or AGENTS.md to force-trigger skills in a project (/golang-how-to configure).
development
Golang performance optimization patterns and methodology - if X bottleneck, then apply Y. Covers allocation reduction, CPU efficiency, memory layout, GC tuning, pooling, caching, and hot-path optimization. Use when profiling or benchmarks have identified a bottleneck and you need the right optimization pattern to fix it. Also use when performing performance code review to suggest improvements or benchmarks that could help identify quick performance gains. Not for measurement methodology (→ See `samber/cc-skills-golang@golang-benchmark` skill) or debugging workflow (→ See `samber/cc-skills-golang@golang-troubleshooting` skill).
development
Implements dependency injection in Golang using uber-go/dig — reflection-based container, Provide/Invoke, dig.In/dig.Out parameter and result objects, named values, value groups, optional dependencies, scopes, and Decorate. Apply when using or adopting uber-go/dig, when the codebase imports `go.uber.org/dig`, or when wiring an application graph at startup. For higher-level lifecycle and modules, see `samber/cc-skills-golang@golang-uber-fx` skill.
development
Troubleshoot Golang programs systematically - find and fix the root cause. Use when encountering bugs, crashes, deadlocks, or unexpected behavior in Go code. Covers debugging methodology, common Go pitfalls, test-driven debugging, pprof setup and capture, Delve debugger, race detection, GODEBUG tracing, and production debugging. Start here for any 'something is wrong' situation. Not for interpreting profiles or benchmarking (→ See `samber/cc-skills-golang@golang-benchmark` skill) or applying optimization patterns (→ See `samber/cc-skills-golang@golang-performance` skill).