golang轻量级依赖注入容器插件库gocontainer的使用
Golang轻量级依赖注入容器插件库gocontainer的使用
关于gocontainer
gocontainer是一个轻量级的依赖注入(Dependency Injection)容器库,由Rafał Lorenz开发。它允许你在Go应用中轻松管理依赖关系。
基本使用示例
1. 从容器获取依赖并打印
package main
import (
"github.com/vardius/gocontainer/example/repository"
"github.com/vardius/gocontainer"
)
func main() {
// 使用MustInvoke方法从容器获取repository.mysql并打印
gocontainer.MustInvoke("repository.mysql", func(r Repository) {
fmt.Println(r)
})
}
2. 数据库服务注册
package database
import (
"fmt"
"database/sql"
"github.com/vardius/gocontainer"
)
// NewDatabase 创建新的数据库连接
func NewDatabase() *sql.DB {
db, _ := sql.Open("mysql", "dsn")
return db
}
// init函数在包导入时自动执行,注册db服务
func init() {
db := gocontainer.MustGet("db")
gocontainer.Register("db", NewDatabase())
}
3. 仓库服务注册
package repository
import (
"fmt"
"database/sql"
"github.com/vardius/gocontainer"
_ "github.com/vardius/gocontainer/example/database" // 导入数据库包以触发init
)
type Repository interface {}
// NewRepository 创建新的仓库实例
func NewRepository(db *sql.DB) Repository {
return &mysqlRepository{db}
}
type mysqlRepository struct {
db *sql.DB
}
// init函数在包导入时自动执行,注册repository.mysql服务
func init() {
db := gocontainer.MustGet("db")
gocontainer.Register("repository.mysql", NewRepository(db.(*sql.DB)))
}
自定义容器实例
你可以禁用全局容器实例并创建自己的容器:
package main
import (
"github.com/vardius/gocontainer/example/repository"
"github.com/vardius/gocontainer"
)
func main() {
// 禁用全局容器实例
gocontainer.GlobalContainer = nil
// 创建新的容器实例
mycontainer := gocontainer.New()
mycontainer.Register("test", 1)
}
主要方法
Register(name string, value interface{})
: 注册服务到容器MustGet(name string) interface{}
: 从容器获取服务(如果不存在会panic)MustInvoke(name string, fn interface{})
: 安全调用容器中的服务New()
: 创建新的容器实例
gocontainer采用MIT许可证发布,是一个轻量级但功能完整的依赖注入解决方案,特别适合需要管理复杂依赖关系的Go应用程序。
更多关于golang轻量级依赖注入容器插件库gocontainer的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang轻量级依赖注入容器插件库gocontainer的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
GoContainer - Golang轻量级依赖注入容器
GoContainer是一个轻量级的依赖注入(DI)容器库,专为Go语言设计。它提供了简单易用的依赖注入功能,可以帮助开发者更好地管理应用程序中的组件依赖关系。
主要特性
- 轻量级设计,无额外依赖
- 支持构造函数注入和接口绑定
- 支持单例和瞬态(transient)生命周期
- 简单易用的API
安装
go get github.com/golobby/container/v3
基本用法
1. 简单绑定与解析
package main
import (
"fmt"
"github.com/golobby/container/v3"
)
type Database struct {
ConnectionString string
}
func main() {
// 绑定实例
err := container.Singleton(func() Database {
return Database{ConnectionString: "mysql://user:pass@localhost:3306/db"}
})
if err != nil {
panic(err)
}
// 解析依赖
var db Database
err = container.Resolve(&db)
if err != nil {
panic(err)
}
fmt.Println(db.ConnectionString) // 输出: mysql://user:pass@localhost:3306/db
}
2. 接口绑定
package main
import (
"fmt"
"github.com/golobby/container/v3"
)
type Logger interface {
Log(message string)
}
type ConsoleLogger struct{}
func (l ConsoleLogger) Log(message string) {
fmt.Println(message)
}
func main() {
// 绑定接口实现
err := container.Singleton(func() Logger {
return ConsoleLogger{}
})
if err != nil {
panic(err)
}
// 解析依赖
var logger Logger
err = container.Resolve(&logger)
if err != nil {
panic(err)
}
logger.Log("Hello, Dependency Injection!") // 输出: Hello, Dependency Injection!
}
3. 构造函数注入
package main
import (
"fmt"
"github.com/golobby/container/v3"
)
type Service struct {
Logger Logger
}
type Logger interface {
Log(message string)
}
type ConsoleLogger struct{}
func (l ConsoleLogger) Log(message string) {
fmt.Println(message)
}
func NewService(logger Logger) Service {
return Service{Logger: logger}
}
func main() {
// 绑定依赖
err := container.Singleton(func() Logger {
return ConsoleLogger{}
})
if err != nil {
panic(err)
}
// 绑定服务,自动注入Logger
err = container.Transient(func(logger Logger) Service {
return NewService(logger)
})
if err != nil {
panic(err)
}
// 解析服务
var service Service
err = container.Resolve(&service)
if err != nil {
panic(err)
}
service.Logger.Log("Service created with DI!") // 输出: Service created with DI!
}
4. 单例与瞬态生命周期
package main
import (
"fmt"
"github.com/golobby/container/v3"
)
type Counter struct {
count int
}
func (c *Counter) Increment() {
c.count++
fmt.Printf("Count: %d\n", c.count)
}
func main() {
// 单例模式 - 每次解析都是同一个实例
err := container.Singleton(func() *Counter {
return &Counter{}
})
if err != nil {
panic(err)
}
// 瞬态模式 - 每次解析都是新实例
err = container.Transient(func() Counter {
return Counter{}
})
if err != nil {
panic(err)
}
// 解析单例
var singleton1, singleton2 *Counter
_ = container.Resolve(&singleton1)
_ = container.Resolve(&singleton2)
singleton1.Increment() // Count: 1
singleton2.Increment() // Count: 2 (同一个实例)
// 解析瞬态
var transient1, transient2 Counter
_ = container.Resolve(&transient1)
_ = container.Resolve(&transient2)
transient1.Increment() // Count: 1
transient2.Increment() // Count: 1 (不同实例)
}
高级用法
命名绑定
package main
import (
"fmt"
"github.com/golobby/container/v3"
)
func main() {
// 命名绑定
err := container.NamedSingleton("db1", func() string {
return "Connection String 1"
})
if err != nil {
panic(err)
}
err = container.NamedSingleton("db2", func() string {
return "Connection String 2"
})
if err != nil {
panic(err)
}
// 解析命名实例
var connStr1, connStr2 string
err = container.NamedResolve(&connStr1, "db1")
if err != nil {
panic(err)
}
err = container.NamedResolve(&connStr2, "db2")
if err != nil {
panic(err)
}
fmt.Println(connStr1) // 输出: Connection String 1
fmt.Println(connStr2) // 输出: Connection String 2
}
条件绑定
package main
import (
"fmt"
"github.com/golobby/container/v3"
)
type Config struct {
Env string
}
type Service struct {
Config Config
}
func NewService(config Config) Service {
return Service{Config: config}
}
func main() {
// 模拟环境配置
config := Config{Env: "production"}
// 绑定配置
err := container.Instance(config)
if err != nil {
panic(err)
}
// 绑定服务
err = container.Transient(func(c Config) Service {
return NewService(c)
})
if err != nil {
panic(err)
}
// 解析服务
var service Service
err = container.Resolve(&service)
if err != nil {
panic(err)
}
fmt.Printf("Service running in %s environment\n", service.Config.Env)
}
最佳实践
- 在应用启动时注册所有依赖:通常在main函数或初始化代码中完成所有绑定
- 优先使用接口:这使得代码更易于测试和维护
- 合理使用生命周期:
- 单例(Singleton):适用于无状态服务、配置、数据库连接等
- 瞬态(Transient):适用于有状态服务,每次需要新实例的情况
- 避免服务定位器模式:尽量使用构造函数注入,而不是在代码中直接解析依赖
总结
GoContainer是一个简单而强大的依赖注入容器,它可以帮助你更好地组织Go应用程序的依赖关系。通过使用依赖注入,你的代码将变得更加模块化、可测试和可维护。虽然它没有一些更复杂的DI框架(如Dig或Wire)的所有功能,但对于大多数中小型项目来说,它提供了足够的功能且保持了简单性。
对于更复杂的场景,你可能需要考虑其他DI框架,但对于大多数用例,GoContainer提供了一个很好的平衡点,既足够强大又保持简单易用。