$npx -y skills add samber/cc-skills-golang --skill golang-dependency-injectionComprehensive 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/wire, uber-go/dig, uber-go/fx, samber/do). Use this skil
| 1 | **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. |
| 2 | |
| 3 | **Orchestration mode:** Use `ultracode` when refactoring a large coupled codebase toward dependency injection — orchestrate the three sub-agents described in Refactor mode (global/init discovery, concrete-dependency mapping, service-locator detection) and consolidate into one migration plan. |
| 4 | |
| 5 | **Modes:** |
| 6 | |
| 7 | - **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. |
| 8 | - **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. |
| 9 | |
| 10 | > **Community default.** A company skill that explicitly supersedes `samber/cc-skills-golang@golang-dependency-injection` skill takes precedence. |
| 11 | |
| 12 | # Dependency Injection in Go |
| 13 | |
| 14 | Dependency 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. |
| 15 | |
| 16 | This skill is not exhaustive. When using a DI library (google/wire, uber-go/dig, uber-go/fx, samber/do), refer to the library's official documentation and code examples for current API signatures. |
| 17 | |
| 18 | For interface-based design foundations (accept interfaces, return structs), see the `samber/cc-skills-golang@golang-structs-interfaces` skill. |
| 19 | |
| 20 | ## Best Practices Summary |
| 21 | |
| 22 | 1. Dependencies MUST be injected via constructors — NEVER use global variables or `init()` for service setup |
| 23 | 2. Small projects (< 10 services) SHOULD use manual constructor injection — no library needed |
| 24 | 3. Interfaces MUST be defined where consumed, not where implemented — accept interfaces, return structs |
| 25 | 4. NEVER use global registries or package-level service locators |
| 26 | 5. The DI container MUST only exist at the composition root (`main()` or app startup) — NEVER pass the container as a dependency |
| 27 | 6. **Prefer lazy initialization** — only create services when first requested |
| 28 | 7. **Use singletons for stateful services** (DB connections, caches) and transients for stateless ones |
| 29 | 8. **Mock at the interface boundary** — DI makes this trivial |
| 30 | 9. **Keep the dependency graph shallow** — deep chains signal design problems |
| 31 | 10. **Choose the right DI library** for your project size and team — see the decision table below |
| 32 | |
| 33 | ## Why Dependency Injection? |
| 34 | |
| 35 | | Problem without DI | How DI solves it | |
| 36 | | --- | --- | |
| 37 | | Functions create their own dependencies | Dependencies are injected — swap implementations freely | |
| 38 | | Testing requires real databases, APIs | Pass mock implementations in tests | |
| 39 | | Changing one component breaks others | Loose coupling via interfaces — components don't know each other's internals | |
| 40 | | Services initialized everywhere | Centralized container manages lifecycle (singleton, factory, lazy) | |
| 41 | | All services loaded at startup | Lazy loading — services created only when first requested | |
| 42 | | Global state and `init()` functions | Explicit wiring at startup — predictable, debuggable | |
| 43 | |
| 44 | DI 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-e |