[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71N7CEKZPTZ9FP6REPCZX74":3,"skill-same:01M71N7CEKZPTZ9FP6REPCZX74":104},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":62,"commitSha":63,"skillDirectory":64,"forksCount":14,"repositoryHtmlUrl":65,"repositoryHomepageUrl":66,"ownerHtmlUrl":67,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":68,"install":69,"resources":81},"01M71N7CEKZPTZ9FP6REPCZX74","golang-dependency-injection",null,"Comprehensive guide for dependency injection (DI) in Golang. Covers why DI matters (testability, loose coupling, separation of concerns, lifecycle management), manual constructor injection, and DI library comparison (google\u002Fwire, uber-go\u002Fdig, uber-go\u002Ffx, samber\u002Fdo). Use this skill when designing service architecture, setting up dependency injection, refactoring tightly coupled code, managing singletons or service factories, or when the user asks about inversion of control, service containers, or wiring dependencies in Go. For a specific DI library, → See `samber\u002Fcc-skills-golang@golang-google-wire`, `samber\u002Fcc-skills-golang@golang-uber-dig`, `samber\u002Fcc-skills-golang@golang-uber-fx`, or `samber\u002Fcc-skills-golang@golang-samber-do` skills.","pattanation\u002FNorvik","pattanation","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F235419268?v=4","01M71M5THHYYB15ME8R2E4FCZG","Patta","01M71M5TJM1NDM992M8PDKYR2K",0,"MIT","https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fgolang-dependency-injection\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"golang","injection","dependency injection","golang dependency injection","dependency","read","when","wiring","separation of concerns","query","context7","up","MCP","projects","refactoring","Bash","why","code","ai coding agents","architecture","2026-11-10 10:56:23",false,"---\nname: golang-dependency-injection\ndescription: \"Comprehensive guide for dependency injection (DI) in Golang. Covers why DI matters (testability, loose coupling, separation of concerns, lifecycle management), manual constructor injection, and DI library comparison (google\u002Fwire, uber-go\u002Fdig, uber-go\u002Ffx, samber\u002Fdo). Use this skill when designing service architecture, setting up dependency injection, refactoring tightly coupled code, managing singletons or service factories, or when the user asks about inversion of control, service containers, or wiring dependencies in Go. For a specific DI library, → See `samber\u002Fcc-skills-golang@golang-google-wire`, `samber\u002Fcc-skills-golang@golang-uber-dig`, `samber\u002Fcc-skills-golang@golang-uber-fx`, or `samber\u002Fcc-skills-golang@golang-samber-do` skills.\"\nuser-invocable: true\nlicense: MIT\ncompatibility: Designed for Claude Code or similar AI coding agents, and for projects using Golang.\nmetadata:\n  author: samber\n  version: \"1.2.2\"\n  openclaw:\n    emoji: \"🔌\"\n    homepage: https:\u002F\u002Fgithub.com\u002Fsamber\u002Fcc-skills-golang\n    requires:\n      bins:\n        - go\n    install: []\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs AskUserQuestion\n---\n\n**Persona:** You are a Go software architect. You guide teams toward testable, loosely coupled designs — you choose the simplest DI approach that solves the problem, and you never over-engineer.\n\n**Orchestration mode:** Use `ultracode` when refactoring a large coupled codebase toward dependency injection — orchestrate the three sub-agents described in Refactor mode (global\u002Finit discovery, concrete-dependency mapping, service-locator detection) and consolidate into one migration plan.\n\n**Modes:**\n\n- **Design mode** (new project, new service, or adding a service to an existing DI setup): assess the existing dependency graph and lifecycle needs; recommend manual injection or a library from the decision table; then generate the wiring code.\n- **Refactor mode** (existing coupled code): use up to 3 parallel sub-agents — Agent 1 identifies global variables and `init()` service setup, Agent 2 maps concrete type dependencies that should become interfaces, Agent 3 locates service-locator anti-patterns (container passed as argument) — then consolidate findings and propose a migration plan.\n\n> **Community default.** A company skill that explicitly supersedes `samber\u002Fcc-skills-golang@golang-dependency-injection` skill takes precedence.\n\n# Dependency Injection in Go\n\nDependency injection (DI) means passing dependencies to a component rather than having it create or find them. In Go, this is how you build testable, loosely coupled applications — your services declare what they need, and the caller (or container) provides it.\n\nThis skill is not exhaustive. When using a DI library (google\u002Fwire, uber-go\u002Fdig, uber-go\u002Ffx, samber\u002Fdo), refer to the library's official documentation and code examples for current API signatures.\n\nFor interface-based design foundations (accept interfaces, return structs), see the `samber\u002Fcc-skills-golang@golang-structs-interfaces` skill.\n\n## Best Practices Summary\n\n1. Dependencies MUST be injected via constructors — NEVER use global variables or `init()` for service setup\n2. Small projects (\u003C 10 services) SHOULD use manual constructor injection — no library needed\n3. Interfaces MUST be defined where consumed, not where implemented — accept interfaces, return structs\n4. NEVER use global registries or package-level service locators\n5. The DI container MUST only exist at the composition root (`main()` or app startup) — NEVER pass the container as a dependency\n6. **Prefer lazy initialization** — only create services when first requested\n7. **Use singletons for stateful services** (DB connections, caches) and transients for stateless ones\n8. **Mock at the interface boundary** — DI makes this trivial\n9. **Keep the dependency graph shallow** — deep chains signal design problems\n10. **Choose the right DI library** for your project size and team — see the decision table below\n\n## Why Dependency Injection?\n\n| Problem without DI | How DI solves it |\n| --- | --- |\n| Functions create their own dependencies | Dependencies are injected — swap implementations freely |\n| Testing requires real databases, APIs | Pass mock implementations in tests |\n| Changing one component breaks others | Loose coupling via interfaces — components don't know each other's internals |\n| Services initialized everywhere | Centralized container manages lifecycle (singleton, factory, lazy) |\n| All services loaded at startup | Lazy loading — services created only when first requested |\n| Global state and `init()` functions | Explicit wiring at startup — predictable, debuggable |\n\nDI shines in applications with many interconnected services — HTTP servers, microservices, CLI tools with plugins. For a small script with 2-3 functions, manual wiring is fine. Don't over-engineer.\n\n## Manual Constructor Injection (No Library)\n\nFor small projects, pass dependencies through constructors. See [Manual DI examples](.\u002Freferences\u002Fmanual-di.md) for a complete application example.\n\n```go\n\u002F\u002F ✓ Good — explicit dependencies, testable\ntype UserService struct {\n    db     UserStore\n    mailer Mailer\n    logger *slog.Logger\n}\n\nfunc NewUserService(db UserStore, mailer Mailer, logger *slog.Logger) *UserService {\n    return &UserService{db: db, mailer: mailer, logger: logger}\n}\n\n\u002F\u002F main.go — manual wiring\nfunc main() {\n    logger := slog.Default()\n    db := postgres.NewUserStore(connStr)\n    mailer := smtp.NewMailer(smtpAddr)\n    userSvc := NewUserService(db, mailer, logger)\n    orderSvc := NewOrderService(db, logger)\n    api := NewAPI(userSvc, orderSvc, logger)\n    api.ListenAndServe(\":8080\")\n}\n```\n\n```go\n\u002F\u002F ✗ Bad — hardcoded dependencies, untestable\ntype UserService struct {\n    db *sql.DB\n}\n\nfunc NewUserService() *UserService {\n    db, _ := sql.Open(\"postgres\", os.Getenv(\"DATABASE_URL\")) \u002F\u002F hidden dependency\n    return &UserService{db: db}\n}\n```\n\nManual DI breaks down when:\n\n- You have 15+ services with cross-dependencies\n- You need lifecycle management (health checks, graceful shutdown)\n- You want lazy initialization or scoped containers\n- Wiring order becomes fragile and hard to maintain\n\n## DI Library Comparison\n\nGo has three main approaches to DI libraries:\n\n- [google\u002Fwire examples](.\u002Freferences\u002Fgoogle-wire.md) — Compile-time code generation\n- [uber-go\u002Fdig + fx examples](.\u002Freferences\u002Fuber-dig-fx.md) — Reflection-based framework\n- [samber\u002Fdo examples](.\u002Freferences\u002Fsamber-do.md) — Generics-based, no code generation\n\n### Decision Table\n\n| Criteria | Manual | google\u002Fwire | uber-go\u002Fdig + fx | samber\u002Fdo |\n| --- | --- | --- | --- | --- |\n| **Project size** | Small (\u003C 10 services) | Medium-Large | Large | Any size |\n| **Type safety** | Compile-time | Compile-time (codegen) | Runtime (reflection) | Compile-time (generics) |\n| **Code generation** | None | Required (`wire_gen.go`) | None | None |\n| **Reflection** | None | None | Yes | None |\n| **API style** | N\u002FA | Provider sets + build tags | Struct tags + decorators | Simple, generic functions |\n| **Lazy loading** | Manual | N\u002FA (all eager) | Built-in (fx) | Built-in |\n| **Singletons** | Manual | Built-in | Built-in | Built-in |\n| **Transient\u002Ffactory** | Manual | Manual | Built-in | Built-in |\n| **Scopes\u002Fmodules** | Manual | Provider sets | Module system (fx) | Built-in (hierarchical) |\n| **Health checks** | Manual | Manual | Manual | Built-in interface |\n| **Graceful shutdown** | Manual | Manual | Built-in (fx) | Built-in interface |\n| **Container cloning** | N\u002FA | N\u002FA | N\u002FA | Built-in |\n| **Debugging** | Print statements | Compile errors | `fx.Visualize()` | `ExplainInjector()`, web interface |\n| **Go version** | Any | Any | Any | 1.18+ (generics) |\n| **Learning curve** | None | Medium | High | Low |\n\n### Quick Comparison: Same App, Four Ways\n\nThe dependency graph: `Config -> Database -> UserStore -> UserService -> API`\n\n**Manual**:\n\n```go\ncfg := NewConfig()\ndb := NewDatabase(cfg)\nstore := NewUserStore(db)\nsvc := NewUserService(store)\napi := NewAPI(svc)\napi.Run()\n\u002F\u002F No automatic shutdown, health checks, or lazy loading\n```\n\n**google\u002Fwire**:\n\n```go\n\u002F\u002F wire.go — then run: wire .\u002F...\nfunc InitializeAPI() (*API, error) {\n    wire.Build(NewConfig, NewDatabase, NewUserStore, NewUserService, NewAPI)\n    return nil, nil\n}\n\u002F\u002F No lifecycle hooks (OnStart\u002FOnStop) or health checks; cleanup via returned func() from providers\n```\n\n**uber-go\u002Ffx**:\n\n```go\napp := fx.New(\n    fx.Provide(NewConfig, NewDatabase, NewUserStore, NewUserService),\n    fx.Invoke(func(api *API) { api.Run() }),\n)\napp.Run() \u002F\u002F manages lifecycle, but reflection-based\n```\n\n**samber\u002Fdo**:\n\n```go\ni := do.New()\ndo.Provide(i, NewConfig)\ndo.Provide(i, NewDatabase)    \u002F\u002F auto shutdown + health check\ndo.Provide(i, NewUserStore)\ndo.Provide(i, NewUserService)\napi := do.MustInvoke[*API](i)\napi.Run()\n\u002F\u002F defer i.Shutdown() — handles all cleanup automatically\n```\n\n## Testing with DI\n\nDI makes testing straightforward — inject mocks instead of real implementations:\n\n```go\n\u002F\u002F Define a mock\ntype MockUserStore struct {\n    users map[string]*User\n}\n\nfunc (m *MockUserStore) FindByID(ctx context.Context, id string) (*User, error) {\n    u, ok := m.users[id]\n    if !ok {\n        return nil, ErrNotFound\n    }\n    return u, nil\n}\n\n\u002F\u002F Test with manual injection\nfunc TestUserService_GetUser(t *testing.T) {\n    mock := &MockUserStore{\n        users: map[string]*User{\"1\": {ID: \"1\", Name: \"Alice\"}},\n    }\n    svc := NewUserService(mock, nil, slog.Default())\n\n    user, err := svc.GetUser(context.Background(), \"1\")\n    if err != nil {\n        t.Fatalf(\"unexpected error: %v\", err)\n    }\n    if user.Name != \"Alice\" {\n        t.Errorf(\"got %q, want %q\", user.Name, \"Alice\")\n    }\n}\n```\n\n### Testing with samber\u002Fdo — Clone and Override\n\nContainer cloning creates an isolated copy where you override only the services you need to mock:\n\n```go\nfunc TestUserService_WithDo(t *testing.T) {\n    \u002F\u002F Create a test injector with mock implementation\n    testInjector := do.New()\n\n    \u002F\u002F Provide the mock UserStore interface\n    do.OverrideValue[UserStore](testInjector, &MockUserStore{\n        users: map[string]*User{\"1\": {ID: \"1\", Name: \"Alice\"}},\n    })\n\n    \u002F\u002F Provide other real services as needed\n    do.Provide[*slog.Logger](testInjector, func(i *do.Injector) (*slog.Logger, error) {\n        return slog.Default(), nil\n    })\n\n    svc := do.MustInvoke[*UserService](testInjector)\n    user, err := svc.GetUser(context.Background(), \"1\")\n    \u002F\u002F ... assertions\n}\n```\n\nThis is particularly useful for integration tests where you want most services to be real but need to mock a specific boundary (database, external API, mailer).\n\n## When to Adopt a DI Library\n\n| Signal | Action |\n| --- | --- |\n| \u003C 10 services, simple dependencies | Stay with manual constructor injection |\n| 10-20 services, some cross-cutting concerns | Consider a DI library |\n| 20+ services, lifecycle management needed | Strongly recommended |\n| Need health checks, graceful shutdown | Use a library with built-in lifecycle support |\n| Team unfamiliar with DI concepts | Start manual, migrate incrementally |\n\n## Common Mistakes\n\n| Mistake | Fix |\n| --- | --- |\n| Global variables as dependencies | Pass through constructors or DI container |\n| `init()` for service setup | Explicit initialization in `main()` or container |\n| Depending on concrete types | Accept interfaces at consumption boundaries |\n| Passing the container everywhere (service locator) | Inject specific dependencies, not the container |\n| Deep dependency chains (A->B->C->D->E) | Flatten — most services should depend on repositories and config directly |\n| Creating a new container per request | One container per application; use scopes for request-level isolation |\n\n## Cross-References\n\n- → See `samber\u002Fcc-skills-golang@golang-samber-do` skill for detailed samber\u002Fdo usage patterns\n- → See `samber\u002Fcc-skills-golang@golang-structs-interfaces` skill for interface design and composition\n- → See `samber\u002Fcc-skills-golang@golang-testing` skill for testing with dependency injection\n- → See `samber\u002Fcc-skills-golang@golang-project-layout` skill for DI initialization placement\n\n## References\n\n- [samber\u002Fdo\u002Fv2 documentation](https:\u002F\u002Fdo.samber.dev) | [github.com\u002Fsamber\u002Fdo\u002Fv2](https:\u002F\u002Fgithub.com\u002Fsamber\u002Fdo)\n- [google\u002Fwire user guide](https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fwire\u002Fblob\u002Fmain\u002Fdocs\u002Fguide.md)\n- [uber-go\u002Ffx documentation](https:\u002F\u002Fuber-go.github.io\u002Ffx\u002F)\n- [uber-go\u002Fdig](https:\u002F\u002Fgithub.com\u002Fuber-go\u002Fdig)\n","**Persona:** You are a Go software architect. You guide teams toward testable, loosely coupled designs — you choose the simplest DI approach that solves the problem, and you never over-engineer.\n\n**Orchestration mode:** Use `ultracode` when refactoring a large coupled codebase toward dependency injection — orchestrate the three sub-agents described in Refactor mode (global\u002Finit discovery, concrete-dependency mapping, service-locator detection) and consolidate into one migration plan.\n\n**Modes:**\n\n- **Design mode** (new project, new service, or adding a service to an existing DI setup): assess the existing dependency graph and lifecycle needs; recommend manual injection or a library from the decision table; then generate the wiring code.\n- **Refactor mode** (existing coupled code): use up to 3 parallel sub-agents — Agent 1 identifies global variables and `init()` service setup, Agent 2 maps concrete type dependencies that should become interfaces, Agent 3 locates service-locator anti-patterns (container passed as argument) — then consolidate findings and propose a migration plan.\n\n> **Community default.** A company skill that explicitly supersedes `samber\u002Fcc-skills-golang@golang-dependency-injection` skill takes precedence.\n\n# Dependency Injection in Go\n\nDependency injection (DI) means passing dependencies to a component rather than having it create or find them. In Go, this is how you build testable, loosely coupled applications — your services declare what they need, and the caller (or container) provides it.\n\nThis skill is not exhaustive. When using a DI library (google\u002Fwire, uber-go\u002Fdig, uber-go\u002Ffx, samber\u002Fdo), refer to the library's official documentation and code examples for current API signatures.\n\nFor interface-based design foundations (accept interfaces, return structs), see the `samber\u002Fcc-skills-golang@golang-structs-interfaces` skill.\n\n## Best Practices Summary\n\n1. Dependencies MUST be injected via constructors — NEVER use global variables or `init()` for service setup\n2. Small projects (\u003C 10 services) SHOULD use manual constructor injection — no library needed\n3. Interfaces MUST be defined where consumed, not where implemented — accept interfaces, return structs\n4. NEVER use global registries or package-level service locators\n5. The DI container MUST only exist at the composition root (`main()` or app startup) — NEVER pass the container as a dependency\n6. **Prefer lazy initialization** — only create services when first requested\n7. **Use singletons for stateful services** (DB connections, caches) and transients for stateless ones\n8. **Mock at the interface boundary** — DI makes this trivial\n9. **Keep the dependency graph shallow** — deep chains signal design problems\n10. **Choose the right DI library** for your project size and team — see the decision table below\n\n## Why Dependency Injection?\n\n| Problem without DI | How DI solves it |\n| --- | --- |\n| Functions create their own dependencies | Dependencies are injected — swap implementations freely |\n| Testing requires real databases, APIs | Pass mock implementations in tests |\n| Changing one component breaks others | Loose coupling via interfaces — components don't know each other's internals |\n| Services initialized everywhere | Centralized container manages lifecycle (singleton, factory, lazy) |\n| All services loaded at startup | Lazy loading — services created only when first requested |\n| Global state and `init()` functions | Explicit wiring at startup — predictable, debuggable |\n\nDI shines in applications with many interconnected services — HTTP servers, microservices, CLI tools with plugins. For a small script with 2-3 functions, manual wiring is fine. Don't over-engineer.\n\n## Manual Constructor Injection (No Library)\n\nFor small projects, pass dependencies through constructors. See [Manual DI examples](.\u002Freferences\u002Fmanual-di.md) for a complete application example.\n\n```go\n\u002F\u002F ✓ Good — explicit dependencies, testable\ntype UserService struct {\n    db     UserStore\n    mailer Mailer\n    logger *slog.Logger\n}\n\nfunc NewUserService(db UserStore, mailer Mailer, logger *slog.Logger) *UserService {\n    return &UserService{db: db, mailer: mailer, logger: logger}\n}\n\n\u002F\u002F main.go — manual wiring\nfunc main() {\n    logger := slog.Default()\n    db := postgres.NewUserStore(connStr)\n    mailer := smtp.NewMailer(smtpAddr)\n    userSvc := NewUserService(db, mailer, logger)\n    orderSvc := NewOrderService(db, logger)\n    api := NewAPI(userSvc, orderSvc, logger)\n    api.ListenAndServe(\":8080\")\n}\n```\n\n```go\n\u002F\u002F ✗ Bad — hardcoded dependencies, untestable\ntype UserService struct {\n    db *sql.DB\n}\n\nfunc NewUserService() *UserService {\n    db, _ := sql.Open(\"postgres\", os.Getenv(\"DATABASE_URL\")) \u002F\u002F hidden dependency\n    return &UserService{db: db}\n}\n```\n\nManual DI breaks down when:\n\n- You have 15+ services with cross-dependencies\n- You need lifecycle management (health checks, graceful shutdown)\n- You want lazy initialization or scoped containers\n- Wiring order becomes fragile and hard to maintain\n\n## DI Library Comparison\n\nGo has three main approaches to DI libraries:\n\n- [google\u002Fwire examples](.\u002Freferences\u002Fgoogle-wire.md) — Compile-time code generation\n- [uber-go\u002Fdig + fx examples](.\u002Freferences\u002Fuber-dig-fx.md) — Reflection-based framework\n- [samber\u002Fdo examples](.\u002Freferences\u002Fsamber-do.md) — Generics-based, no code generation\n\n### Decision Table\n\n| Criteria | Manual | google\u002Fwire | uber-go\u002Fdig + fx | samber\u002Fdo |\n| --- | --- | --- | --- | --- |\n| **Project size** | Small (\u003C 10 services) | Medium-Large | Large | Any size |\n| **Type safety** | Compile-time | Compile-time (codegen) | Runtime (reflection) | Compile-time (generics) |\n| **Code generation** | None | Required (`wire_gen.go`) | None | None |\n| **Reflection** | None | None | Yes | None |\n| **API style** | N\u002FA | Provider sets + build tags | Struct tags + decorators | Simple, generic functions |\n| **Lazy loading** | Manual | N\u002FA (all eager) | Built-in (fx) | Built-in |\n| **Singletons** | Manual | Built-in | Built-in | Built-in |\n| **Transient\u002Ffactory** | Manual | Manual | Built-in | Built-in |\n| **Scopes\u002Fmodules** | Manual | Provider sets | Module system (fx) | Built-in (hierarchical) |\n| **Health checks** | Manual | Manual | Manual | Built-in interface |\n| **Graceful shutdown** | Manual | Manual | Built-in (fx) | Built-in interface |\n| **Container cloning** | N\u002FA | N\u002FA | N\u002FA | Built-in |\n| **Debugging** | Print statements | Compile errors | `fx.Visualize()` | `ExplainInjector()`, web interface |\n| **Go version** | Any | Any | Any | 1.18+ (generics) |\n| **Learning curve** | None | Medium | High | Low |\n\n### Quick Comparison: Same App, Four Ways\n\nThe dependency graph: `Config -> Database -> UserStore -> UserService -> API`\n\n**Manual**:\n\n```go\ncfg := NewConfig()\ndb := NewDatabase(cfg)\nstore := NewUserStore(db)\nsvc := NewUserService(store)\napi := NewAPI(svc)\napi.Run()\n\u002F\u002F No automatic shutdown, health checks, or lazy loading\n```\n\n**google\u002Fwire**:\n\n```go\n\u002F\u002F wire.go — then run: wire .\u002F...\nfunc InitializeAPI() (*API, error) {\n    wire.Build(NewConfig, NewDatabase, NewUserStore, NewUserService, NewAPI)\n    return nil, nil\n}\n\u002F\u002F No lifecycle hooks (OnStart\u002FOnStop) or health checks; cleanup via returned func() from providers\n```\n\n**uber-go\u002Ffx**:\n\n```go\napp := fx.New(\n    fx.Provide(NewConfig, NewDatabase, NewUserStore, NewUserService),\n    fx.Invoke(func(api *API) { api.Run() }),\n)\napp.Run() \u002F\u002F manages lifecycle, but reflection-based\n```\n\n**samber\u002Fdo**:\n\n```go\ni := do.New()\ndo.Provide(i, NewConfig)\ndo.Provide(i, NewDatabase)    \u002F\u002F auto shutdown + health check\ndo.Provide(i, NewUserStore)\ndo.Provide(i, NewUserService)\napi := do.MustInvoke[*API](i)\napi.Run()\n\u002F\u002F defer i.Shutdown() — handles all cleanup automatically\n```\n\n## Testing with DI\n\nDI makes testing straightforward — inject mocks instead of real implementations:\n\n```go\n\u002F\u002F Define a mock\ntype MockUserStore struct {\n    users map[string]*User\n}\n\nfunc (m *MockUserStore) FindByID(ctx context.Context, id string) (*User, error) {\n    u, ok := m.users[id]\n    if !ok {\n        return nil, ErrNotFound\n    }\n    return u, nil\n}\n\n\u002F\u002F Test with manual injection\nfunc TestUserService_GetUser(t *testing.T) {\n    mock := &MockUserStore{\n        users: map[string]*User{\"1\": {ID: \"1\", Name: \"Alice\"}},\n    }\n    svc := NewUserService(mock, nil, slog.Default())\n\n    user, err := svc.GetUser(context.Background(), \"1\")\n    if err != nil {\n        t.Fatalf(\"unexpected error: %v\", err)\n    }\n    if user.Name != \"Alice\" {\n        t.Errorf(\"got %q, want %q\", user.Name, \"Alice\")\n    }\n}\n```\n\n### Testing with samber\u002Fdo — Clone and Override\n\nContainer cloning creates an isolated copy where you override only the services you need to mock:\n\n```go\nfunc TestUserService_WithDo(t *testing.T) {\n    \u002F\u002F Create a test injector with mock implementation\n    testInjector := do.New()\n\n    \u002F\u002F Provide the mock UserStore interface\n    do.OverrideValue[UserStore](testInjector, &MockUserStore{\n        users: map[string]*User{\"1\": {ID: \"1\", Name: \"Alice\"}},\n    })\n\n    \u002F\u002F Provide other real services as needed\n    do.Provide[*slog.Logger](testInjector, func(i *do.Injector) (*slog.Logger, error) {\n        return slog.Default(), nil\n    })\n\n    svc := do.MustInvoke[*UserService](testInjector)\n    user, err := svc.GetUser(context.Background(), \"1\")\n    \u002F\u002F ... assertions\n}\n```\n\nThis is particularly useful for integration tests where you want most services to be real but need to mock a specific boundary (database, external API, mailer).\n\n## When to Adopt a DI Library\n\n| Signal | Action |\n| --- | --- |\n| \u003C 10 services, simple dependencies | Stay with manual constructor injection |\n| 10-20 services, some cross-cutting concerns | Consider a DI library |\n| 20+ services, lifecycle management needed | Strongly recommended |\n| Need health checks, graceful shutdown | Use a library with built-in lifecycle support |\n| Team unfamiliar with DI concepts | Start manual, migrate incrementally |\n\n## Common Mistakes\n\n| Mistake | Fix |\n| --- | --- |\n| Global variables as dependencies | Pass through constructors or DI container |\n| `init()` for service setup | Explicit initialization in `main()` or container |\n| Depending on concrete types | Accept interfaces at consumption boundaries |\n| Passing the container everywhere (service locator) | Inject specific dependencies, not the container |\n| Deep dependency chains (A->B->C->D->E) | Flatten — most services should depend on repositories and config directly |\n| Creating a new container per request | One container per application; use scopes for request-level isolation |\n\n## Cross-References\n\n- → See `samber\u002Fcc-skills-golang@golang-samber-do` skill for detailed samber\u002Fdo usage patterns\n- → See `samber\u002Fcc-skills-golang@golang-structs-interfaces` skill for interface design and composition\n- → See `samber\u002Fcc-skills-golang@golang-testing` skill for testing with dependency injection\n- → See `samber\u002Fcc-skills-golang@golang-project-layout` skill for DI initialization placement\n\n## References\n\n- [samber\u002Fdo\u002Fv2 documentation](https:\u002F\u002Fdo.samber.dev) | [github.com\u002Fsamber\u002Fdo\u002Fv2](https:\u002F\u002Fgithub.com\u002Fsamber\u002Fdo)\n- [google\u002Fwire user guide](https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fwire\u002Fblob\u002Fmain\u002Fdocs\u002Fguide.md)\n- [uber-go\u002Ffx documentation](https:\u002F\u002Fuber-go.github.io\u002Ffx\u002F)\n- [uber-go\u002Fdig](https:\u002F\u002Fgithub.com\u002Fuber-go\u002Fdig)\n",{"name":5,"license":15,"metadata":49,"description":7,"allowed-tools":59,"compatibility":60,"user-invocable":61},{"author":50,"version":51,"openclaw":52},"samber","1.2.2",{"emoji":53,"install":54,"homepage":55,"requires":56},"🔌",[],"https:\u002F\u002Fgithub.com\u002Fsamber\u002Fcc-skills-golang",{"bins":57},[58],"go","Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs AskUserQuestion","Designed for Claude Code or similar AI coding agents, and for projects using Golang.",true,"claude\u002Finstall-gsd-build-foQdV","d86cd127f527124b5fd0fd0bc679a4d79b7d01d7",".agents\u002Fskills\u002Fgolang-dependency-injection","https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik","https:\u002F\u002Fnorvik-orpin.vercel.app","https:\u002F\u002Fgithub.com\u002Fpattanation","2026-07-17 11:17:04",{"source":8,"skillName":5,"commands":70,"prompt":80,"zipAvailable":61},[71,74,77],{"tool":72,"command":73},"npx","npx skills add pattanation\u002FNorvik --skill golang-dependency-injection",{"tool":75,"command":76},"bunx","bunx skills add pattanation\u002FNorvik --skill golang-dependency-injection",{"tool":78,"command":79},"pnpm","pnpm dlx skills add pattanation\u002FNorvik --skill golang-dependency-injection","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fgolang-dependency-injection\u002FSKILL.md",[82,88,92,96,100],{"path":83,"resourceType":84,"resourceTypeDesc":85,"sizeBytes":86,"sourceHtmlUrl":87},"evals\u002Fevals.json","REFERENCE","参考文档",12046,"https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fgolang-dependency-injection\u002Fevals\u002Fevals.json",{"path":89,"resourceType":84,"resourceTypeDesc":85,"sizeBytes":90,"sourceHtmlUrl":91},"references\u002Fgoogle-wire.md",2445,"https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fgolang-dependency-injection\u002Freferences\u002Fgoogle-wire.md",{"path":93,"resourceType":84,"resourceTypeDesc":85,"sizeBytes":94,"sourceHtmlUrl":95},"references\u002Fmanual-di.md",2182,"https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fgolang-dependency-injection\u002Freferences\u002Fmanual-di.md",{"path":97,"resourceType":84,"resourceTypeDesc":85,"sizeBytes":98,"sourceHtmlUrl":99},"references\u002Fsamber-do.md",1625,"https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fgolang-dependency-injection\u002Freferences\u002Fsamber-do.md",{"path":101,"resourceType":84,"resourceTypeDesc":85,"sizeBytes":102,"sourceHtmlUrl":103},"references\u002Fuber-dig-fx.md",3500,"https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fgolang-dependency-injection\u002Freferences\u002Fuber-dig-fx.md",[105,138,164,187,209,224],{"skillNo":106,"name":107,"nameZh":6,"description":108,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":109,"licenseFileUrl":110,"sourceHtmlUrl":111,"categories":112,"keywords":119,"publishedAt":137},"01M71QDV4DM8T19HEHWATEF1K4","webapp-testing","Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fwebapp-testing\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fwebapp-testing\u002FSKILL.md",[113,116],{"categoryNo":114,"categoryName":115,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":117,"categoryName":118,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发",[120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136],"webapp","testing","webapp testing","for","applications","local","frontend","debugging","toolkit","logs","browser","with","playwright","web","behavior","ui","screenshots","2026-11-10 13:02:02",{"skillNo":139,"name":140,"nameZh":6,"description":141,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":109,"licenseFileUrl":142,"sourceHtmlUrl":143,"categories":144,"keywords":146,"publishedAt":137},"01M71QDH2GGMXGA9105C9W1N7B","web-artifacts-builder","Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn\u002Fui). Use for complex artifacts requiring state management, routing, or shadcn\u002Fui components - not for simple single-file HTML\u002FJSX artifacts.","https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fweb-artifacts-builder\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fweb-artifacts-builder\u002FSKILL.md",[145],{"categoryNo":117,"categoryName":118,"taxonomyType":21,"taxonomyTypeDesc":22},[147,148,149,133,150,151,152,123,153,154,126,155,156,157,158,159,160,161,162,163],"builder","artifacts builder","artifacts","web artifacts builder","single-file","css","Tailwind","ui components","single","use","file","components","react","multi","state","routing","state management",{"skillNo":165,"name":166,"nameZh":6,"description":167,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":168,"sourceHtmlUrl":169,"categories":170,"keywords":172,"publishedAt":137},"01M71QD9T2XC3EWMQNN9ACNWQ1","vueuse-functions","Apply VueUse composables where appropriate to build concise, maintainable Vue.js \u002F Nuxt features.","https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fvueuse-functions\u002FLICENSE.md","https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fvueuse-functions\u002FSKILL.md",[171],{"categoryNo":117,"categoryName":118,"taxonomyType":21,"taxonomyTypeDesc":22},[173,174,175,176,177,178,179,180,181,182,183,184,185,186],"functions","vueuse","vueuse functions","project","nuxt","apply","github","concise","build","https","features","vue","js","composables",{"skillNo":188,"name":189,"nameZh":6,"description":190,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":191,"sourceHtmlUrl":192,"categories":193,"keywords":196,"publishedAt":137},"01M71QD51HWSGYMCMB7RW7PGK8","vue-testing-best-practices","Use for Vue.js testing. Covers Vitest, Vue Test Utils, component testing, mocking, testing patterns, and Playwright for E2E testing.","https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fvue-testing-best-practices\u002FLICENSE.md","https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fvue-testing-best-practices\u002FSKILL.md",[194,195],{"categoryNo":114,"categoryName":115,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":117,"categoryName":118,"taxonomyType":21,"taxonomyTypeDesc":22},[197,121,198,184,199,132,200,201,202,179,203,123,204,205,206,156,207,185,208],"vue testing best practices","testing best practices","best practices","test","testing patterns","component","vitest","mocking","e2e","utils","patterns","e2e testing",{"skillNo":210,"name":211,"nameZh":6,"description":212,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":213,"sourceHtmlUrl":214,"categories":215,"keywords":217,"publishedAt":137},"01M71QD358H2DJ9THJRBP77T3T","vue-router-best-practices","Vue Router 4 patterns, navigation guards, route params, and route-component lifecycle interactions.","https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fvue-router-best-practices\u002FLICENSE.md","https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fvue-router-best-practices\u002FSKILL.md",[216],{"categoryNo":117,"categoryName":118,"taxonomyType":21,"taxonomyTypeDesc":22},[218,184,219,199,220,202,221,179,207,222,223],"router","vue router best practices","route","guards","navigation","lifecycle",{"skillNo":225,"name":226,"nameZh":6,"description":227,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":228,"sourceHtmlUrl":229,"categories":230,"keywords":232,"publishedAt":137},"01M71QCYPNWDE2MQZ1TF3ED5S4","vue-best-practices","MUST be used for Vue.js tasks. Strongly recommends Composition API with `\u003Cscript setup>` and TypeScript as the standard approach. Covers Vue 3, SSR, Volar, vue-tsc. Load for any Vue, .vue files, Vue Router, Pinia, or Vite with Vue work. ALWAYS use Composition API unless the project explicitly requires Options API.","https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fvue-best-practices\u002FLICENSE.md","https:\u002F\u002Fgithub.com\u002Fpattanation\u002FNorvik\u002Fblob\u002Fclaude\u002Finstall-gsd-build-foQdV\u002F.agents\u002Fskills\u002Fvue-best-practices\u002FSKILL.md",[231],{"categoryNo":117,"categoryName":118,"taxonomyType":21,"taxonomyTypeDesc":22},[233,184,199,234,176,235,236,237,218,238,239,240,241,242,243,123,244,156,245,246],"vue best practices","Composition","files","tasks","api","pinia","work","options","ssr","typescript","as","vite","load","standard"]