Source profileQuality 90/100Review permissions

samber/cc-skills-golang/skills/golang-samber-do/SKILL.md

golang-samber-do

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.

Source repository stars
3,074
Declared platforms
2
Static risk flags
1
Last source update
2026-08-23
Source checked
2026-08-26

Decision brief

What it does: where it fits

Type-safe dependency injection toolkit for Go based on Go 1.18+ generics.

Best for

    Not for

    • Tasks that require unconfirmed production actions or broad system permissions.
    • Environments where the pinned source and install steps cannot be inspected.

    Compatibility matrix

    Platform support, with evidence labels

    PlatformStatusEvidenceWhat to check
    CodexDeclaredSource recordInstall path and trigger
    Claude CodeDeclaredSource recordInstall path and trigger
    CursorNot declaredNo explicit evidencePortability before use
    Gemini CLINot declaredNo explicit evidencePortability before use
    Open the compatibility checker

    Installation

    Inspect first. Install second.

    The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

    Source-detected install commandSource
    npx skills add https://github.com/samber/cc-skills-golang --skill "skills/golang-samber-do"
    Safe inspection promptEditorial

    Inspect the Agent Skill "golang-samber-do" from https://github.com/samber/cc-skills-golang/blob/a18860b303ef1d3d928f9670631e03210b8698bf/skills/golang-samber-do/SKILL.md at commit a18860b303ef1d3d928f9670631e03210b8698bf. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

    Workflow

    What the source asks the agent to do

    1. 01

      Basic Usage

      Follow "Accept Interfaces, Return Structs":

      Follow "Accept Interfaces, Return Structs":The container MUST only be accessed at the composition root:Inside a provider function, always use do.MustInvoke (or MustInvokeAs/MustInvokeNamed/MustInvokeStruct) rather than the error-returning variant. A provider already returns (T, error), so propagating a dependency failure…
    2. 02

      Full Application Setup

      Review the “Full Application Setup” section in the pinned source before continuing.

      Review and apply the “Full Application Setup” source section.
    3. 03

      Core Concepts

      Services MUST be registered via provider functions:

      Lazy (default): Created when first requestedEager: Created immediately when the container startsTransient: New instance created on every request
    4. 04

      The Injector (Container)

      Review the “The Injector (Container)” section in the pinned source before continuing.

      Review and apply the “The Injector (Container)” source section.
    5. 05

      Service Types

      Lazy (default): Created when first requested

      Lazy (default): Created when first requestedEager: Created immediately when the container startsTransient: New instance created on every request

    Permission review

    Static risk signals and limitations

    Runs scripts

    medium · line 18

    The documentation asks the agent to run terminal commands or scripts.

    go get -u github.com/samber/do/v2

    Evidence record

    Why each signal appears

    EvidenceSourceComputedTestedEditorial
    SignalValueEvidence typeMeaning
    Quality score90/100ComputedDocumentation, specificity, maintenance, and trust rules
    Repository stars3,074SourceRepository attention, not individual Skill quality
    Compatibility2 platformsSourceDeclared in the catalog source record
    Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

    Pinned source

    Provenance and original SKILL.md

    Repository
    samber/cc-skills-golang
    Skill path
    skills/golang-samber-do/SKILL.md
    Commit
    a18860b303ef1d3d928f9670631e03210b8698bf
    License
    MIT
    Collected
    2026-08-26
    Default branch
    main
    View the original SKILL.md

    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.

    Using samber/do for Dependency Injection in Go

    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. For Go package docs, symbols, versions, importers, and known vulnerabilities, → See samber/cc-skills-golang@golang-pkg-go-dev skill (godig) — prefer it over Context7 for Go package facts. To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See samber/cc-skills-golang@golang-gopls skill (gopls). Context7 remains a fallback for docs not indexed on pkg.go.dev.

    DO NOT USE v1 OF THIS LIBRARY. INSTALL v2 INSTEAD:

    go get -u github.com/samber/do/v2
    

    Core Concepts

    The Injector (Container)

    import "github.com/samber/do/v2"
    
    injector := do.New()
    

    Service Types

    • Lazy (default): Created when first requested
    • Eager: Created immediately when the container starts
    • Transient: New instance created on every request
    • Value: Pre-created value, no instantiation

    Provider Functions

    Services MUST be registered via provider functions:

    type Provider[T any] func(i Injector) (T, error)
    

    Basic Usage

    1. Define and Register Services

    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})
    

    2. Invoke Services

    The container MUST only be accessed at the composition root:

    // Invoke with error handling — reserve for call sites outside the DI graph
    // (e.g. an HTTP handler that must degrade gracefully instead of crashing)
    db, err := do.Invoke[Database](injector)
    
    // MustInvoke panics on error — preferred in providers, recovered by do.Invoke on the parent call
    db := do.MustInvoke[Database](injector)
    

    Inside a provider function, always use do.MustInvoke (or MustInvokeAs/MustInvokeNamed/MustInvokeStruct) rather than the error-returning variant. A provider already returns (T, error), so propagating a dependency failure with do.Invoke costs an extra if err != nil { return nil, err } on every call. do.MustInvoke panics instead, but samber/do correctly catches and recovers that panic at the enclosing Invoke call and converts it back into a regular error — this recover happens inside the library itself, not in caller code, so MustInvoke is safe to use inside providers. The failure still surfaces as an error at the composition root, just without the manual boilerplate in every provider.

    3. Service Dependencies

    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)
    

    4. Implicit Aliasing (Preferred)

    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)
    

    5. Named Services

    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")
    

    Package Organization

    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)
    

    Full Application Setup

    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)
    }
    

    Best Practices

    1. Depend on interfaces, not concrete types — lets you swap implementations in tests without touching production code
    2. Each service should have one job — services with multiple responsibilities are harder to test and harder to replace
    3. Keep dependency trees shallow — chains beyond 3-4 levels make initialization order fragile and errors harder to trace
    4. Handle errors in provider functions — a silently failing provider creates a broken service that crashes later in unexpected places
    5. Use scopes to organize services by lifecycle — request-scoped services prevent leaks, global services prevent redundant initialization
    6. Use do.MustInvoke* inside provider functions instead of do.Invoke* — samber/do correctly catches and recovers the panic at the outer Invoke call, turning it back into a returned error, so it's safe to use inside providers and you get the same error propagation without the boilerplate

    For scopes, lifecycle management, struct injection, and debugging, see Advanced Usage.

    For testing patterns (cloning, overrides, mocks), see Testing.

    Quick Reference

    Registration

    FunctionPurpose
    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

    Invocation

    FunctionPurpose
    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)

    Cross-References

    • → See samber/cc-skills-golang@golang-dependency-injection skill for DI concepts, comparison, and when to adopt a DI library
    • → See samber/cc-skills-golang@golang-structs-interfaces skill for interface design patterns
    • → See samber/cc-skills-golang@golang-testing skill for general testing patterns

    Frequently asked questions

    What to verify before installation and use

    What does the golang-samber-do source document cover?

    Type-safe dependency injection toolkit for Go based on Go 1.18+ generics.

    How do I install golang-samber-do?

    The source record exposes this install command: npx skills add https://github.com/samber/cc-skills-golang --skill "skills/golang-samber-do". Inspect the command and pinned source before running it.

    Which Agent platforms does the source record declare?

    The pinned source record declares support for: codex, claude code.

    Which permission-related actions were detected?

    Static rules flagged exec-script in the source; the page lists the matching lines and excerpts.

    Alternatives

    Compare before choosing