golang-samber-do by samber/cc-skills-golang
npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-do角色: 你是一位正在设置依赖注入的 Go 架构师。你将容器保持在组合根,依赖接口而非具体类型,并将提供者错误视为首要故障。
基于 Go 1.18+ 泛型的类型安全依赖注入工具包。
官方资源:
此技能并非详尽无遗。更多信息请参阅库文档和代码示例。Context7 可以作为一个可发现性平台提供帮助。
切勿使用此库的 v1 版本。请安装 v2 版本:
go get -u github.com/samber/do/v2
import "github.com/samber/do/v2"
injector := do.New()
服务通过提供者函数注册:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
type Provider[T any] func(i Injector) (T, error)
遵循"接受接口,返回结构体"原则:
// 注册一个服务(默认惰性)
do.Provide(injector, func(i do.Injector) (Database, error) {
return &PostgreSQLDatabase{connString: "postgres://..."}, nil
})
// 注册一个预创建的值
do.ProvideValue(injector, &Config{Port: 8080})
// 注册一个瞬时服务(每次新实例)
do.ProvideTransient(injector, func(i do.Injector) (*Logger, error) {
return &Logger{}, nil
})
// 注册一个急切服务(立即创建)
do.Provide(injector, do.Eager(&Config{Port: 8080}))
容器必须仅在组合根处访问:
// 调用并处理错误
db, err := do.Invoke[Database](injector)
// MustInvoke 在出错时 panic(确信服务存在时使用)
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)
注册具体类型并直接作为接口调用,无需显式别名:
// 注册具体类型
do.Provide(injector, func(i do.Injector) (*PostgreSQLDatabase, error) {
return &PostgreSQLDatabase{}, nil
})
// 直接作为接口调用(隐式别名)
db := do.MustInvokeAs[Database](injector)
注册多个相同类型的服务:
do.ProvideNamed(injector, "primary-db", func(i do.Injector) (*Database, error) {
return &Database{URL: "postgres://primary..."}, nil
})
mainDB := do.MustInvokeNamed[*Database](injector, "primary-db")
使用 do.Package() 按模块组织服务注册:
// 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)
}
关于作用域、生命周期管理、结构体注入和调试,请参阅高级用法。
关于测试模式(克隆、覆盖、模拟),请参阅测试。
| 函数 | 用途 |
|---|---|
do.Provide[T]() | 注册惰性服务(默认) |
do.ProvideNamed[T]() | 注册命名惰性服务 |
do.ProvideValue[T]() | 注册预创建的值 |
do.ProvideNamedValue[T]() | 注册命名值 |
do.ProvideTransient[T]() | 注册每次新实例的瞬时服务 |
do.ProvideNamedTransient[T]() | 注册命名瞬时服务 |
do.Package() | 分组服务注册 |
| 函数 | 用途 |
|---|---|
do.Invoke[T]() | 获取服务(带错误) |
do.InvokeNamed[T]() | 获取命名服务 |
do.InvokeAs[T]() | 获取第一个匹配接口的服务 |
do.InvokeStruct[T]() | 使用标签注入到结构体字段 |
do.MustInvoke[T]() | 获取服务(出错时 panic) |
do.MustInvokeNamed[T]() | 获取命名服务(出错时 panic) |
do.MustInvokeAs[T]() | 按接口获取服务(出错时 panic) |
do.MustInvokeStruct[T]() | 注入到结构体(出错时 panic) |
samber/cc-skills-golang@golang-dependency-injection 技能,了解 DI 概念、比较以及何时采用 DI 库samber/cc-skills-golang@golang-structs-interfaces 技能,了解接口设计模式samber/cc-skills-golang@golang-testing 技能,了解通用测试模式每周安装数
93
代码仓库
GitHub 星标数
184
首次出现
3 天前
安全审计
已安装于
opencode75
codex74
gemini-cli74
cursor74
kimi-cli73
github-copilot73
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 informations. 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)
do.Provide(injector, do.Eager(&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]() |
| 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]() |
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 patternsWeekly Installs
93
Repository
GitHub Stars
184
First Seen
3 days ago
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode75
codex74
gemini-cli74
cursor74
kimi-cli73
github-copilot73
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
120,000 周安装
| Register named transient service |
do.Package() | Group service registrations |
| 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) |