golang自定义依赖注入容器插件kinit的使用
Golang自定义依赖注入容器插件kinit的使用
KInit简介
KInit是一个Go语言的依赖注入容器库,提供全局IoC容器实现自动依赖注入功能。
安装
go get github.com/go-kata/kinit
当前状态
这是一个beta版本,API尚未稳定。
版本说明
在第一个主要版本发布前,次版本号(v0.x.0
)应被视为主要版本,补丁版本(v0.0.x
)应被视为次版本。
基本使用
获取容器
获取全局容器:
kinit.Global()
创建本地容器:
ctr := kinit.NewContainer()
构造器(Constructors)
构造器用于创建对象(依赖项),接口定义如下:
type Constructor interface {
Type() reflect.Type
Parameters() []reflect.Type
Create(a ...reflect.Value) (reflect.Value, kdone.Destructor, error)
}
注册构造器:
kinitx.MustProvide(func(config *Config) (*Object, kdone.Destructor, error) { ... })
处理器(Processors)
处理器用于处理已创建的对象,接口定义如下:
type Processor interface {
Type() reflect.Type
Parameters() []reflect.Type
Process(obj reflect.Value, a ...reflect.Value) error
}
注册处理器:
kinitx.MustAttach((*Object).SetOptionalProperty)
函子(Functors)
函子表示要在容器中运行的函数,接口定义如下:
type Functor interface {
Parameters() []reflect.Type
Call(a ...reflect.Value) ([]Functor, error)
}
运行函子:
kinitx.MustRun(func(app *Application) error { ... })
KInitX扩展包
KInitX提供了主要接口的默认实现和其他便捷工具。
构造器实现
// 基于函数的构造器
kinitx.MustProvide(func(config *Config) (*Object, kdone.Destructor, error) { ... })
// 基于io.Closer的构造器
kinitx.MustProvide(func(logger *log.Logger) (*sql.DB, error) { ... })
// 结构体成员初始化器
kinitx.MustProvide((*Config)(nil))
绑定器
kinitx.MustBind((*StorageInterface)(nil), (*PostgresStrorage)(nil))
完整示例
package main
import (
"github.com/go-kata/kinit/kinitx"
"log"
"database/sql"
)
// Config 配置结构体
type Config struct {
DSN string
}
// Service 服务接口
type Service interface {
DoSomething()
}
// RealService 服务实现
type RealService struct{}
func (s *RealService) DoSomething() {
log.Println("Doing something...")
}
func main() {
// 注册构造器
kinitx.MustProvide(func() *Config {
return &Config{DSN: "user:password@/dbname"}
})
kinitx.MustProvide(func(config *Config) (*sql.DB, error) {
return sql.Open("mysql", config.DSN)
})
kinitx.MustProvide(func() *RealService {
return &RealService{}
})
// 绑定接口
kinitx.MustBind((*Service)(nil), (*RealService)(nil))
// 运行主函数
kinitx.MustRun(func(svc Service, db *sql.DB) error {
svc.DoSomething()
// 使用db...
return nil
})
}
依赖图验证(KInitQ)
添加检查代码:
main.go
:
// +build !inspect
package main
import "github.com/go-kata/kinit/kinitx"
func main() { kinitx.MustRun(EntryPoint) }
main_inspect.go
:
// +build inspect
package main
import "github.com/go-kata/kinit/kinitx"
func main() { kinitx.MustInspect(nil) }
运行检查:
go run -tags inspect
相关项目
更多关于golang自定义依赖注入容器插件kinit的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang自定义依赖注入容器插件kinit的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 自定义依赖注入容器插件 Kinit 使用指南
Kinit 是一个轻量级的 Golang 依赖注入容器,它可以帮助你管理应用程序中的依赖关系,实现松耦合的设计。下面我将详细介绍如何使用 Kinit。
基本概念
Kinit 的核心概念包括:
- Provider - 提供依赖项的创建逻辑
- Constructor - 实际创建依赖项的函数
- Container - 管理依赖项的生命周期和注入
安装
go get github.com/go-kata/kinit
基础用法
1. 创建容器
package main
import (
"fmt"
"github.com/go-kata/kinit"
)
type Database struct {
ConnString string
}
type Logger struct {
Level string
}
func main() {
// 创建容器
ctr := kinit.NewContainer()
// 注册提供者
ctr.MustProvide(func() *Database {
return &Database{ConnString: "user:pass@localhost:5432/db"}
})
ctr.MustProvide(func() *Logger {
return &Logger{Level: "debug"}
})
// 使用依赖
err := ctr.Invoke(func(db *Database, logger *Logger) {
fmt.Printf("Database: %+v\n", db)
fmt.Printf("Logger: %+v\n", logger)
})
if err != nil {
panic(err)
}
}
2. 带参数的构造函数
func NewDatabase(config *Config) *Database {
return &Database{ConnString: config.DBConnString}
}
func NewLogger(config *Config) *Logger {
return &Logger{Level: config.LogLevel}
}
type Config struct {
DBConnString string
LogLevel string
}
func main() {
ctr := kinit.NewContainer()
// 先注册配置
ctr.MustProvide(func() *Config {
return &Config{
DBConnString: "user:pass@localhost:5432/db",
LogLevel: "info",
}
})
// 注册依赖
ctr.MustProvide(NewDatabase)
ctr.MustProvide(NewLogger)
// 使用
err := ctr.Invoke(func(db *Database, logger *Logger) {
fmt.Printf("Database: %s\n", db.ConnString)
fmt.Printf("Logger level: %s\n", logger.Level)
})
if err != nil {
panic(err)
}
}
高级特性
1. 接口绑定
type UserRepository interface {
FindByID(id int) string
}
type userRepoImpl struct{}
func (r *userRepoImpl) FindByID(id int) string {
return fmt.Sprintf("User%d", id)
}
func NewUserRepo() UserRepository {
return &userRepoImpl{}
}
func main() {
ctr := kinit.NewContainer()
ctr.MustProvide(NewUserRepo)
err := ctr.Invoke(func(repo UserRepository) {
fmt.Println(repo.FindByID(1)) // 输出: User1
})
if err != nil {
panic(err)
}
}
2. 生命周期管理
func main() {
ctr := kinit.NewContainer()
// 单例模式
ctr.MustProvide(func() *Database {
fmt.Println("Creating database connection")
return &Database{ConnString: "singleton_conn"}
}, kinit.Singleton())
// 每次调用都新建实例
ctr.MustProvide(func() *Logger {
fmt.Println("Creating new logger instance")
return &Logger{Level: "debug"}
})
// 第一次调用
_ = ctr.Invoke(func(db *Database, logger *Logger) {
fmt.Printf("DB: %p, Logger: %p\n", db, logger)
})
// 第二次调用
_ = ctr.Invoke(func(db *Database, logger *Logger) {
fmt.Printf("DB: %p, Logger: %p\n", db, logger)
})
// 输出:
// Creating database connection
// Creating new logger instance
// DB: 0xc000010030, Logger: 0xc000010038
// Creating new logger instance
// DB: 0xc000010030, Logger: 0xc000010040
}
3. 可选依赖
func main() {
ctr := kinit.NewContainer()
// 注册可选依赖
ctr.MustProvide(func() (*Logger, error) {
return &Logger{Level: "debug"}, nil
})
// 使用可选依赖
err := ctr.Invoke(func(logger *Logger) {
fmt.Println("Logger is present")
})
if err != nil {
fmt.Println("Logger is missing")
}
}
最佳实践
- 分层注册:按照模块分层注册依赖
- 接口编程:尽量依赖接口而非具体实现
- 错误处理:构造函数可以返回错误
- 生命周期:合理使用单例和临时实例
完整示例
package main
import (
"fmt"
"github.com/go-kata/kinit"
)
// 配置
type Config struct {
DBConnString string
LogLevel string
}
// 数据库
type Database struct {
connString string
}
func NewDatabase(config *Config) *Database {
return &Database{connString: config.DBConnString}
}
func (db *Database) Query() string {
return "query result"
}
// 日志
type Logger interface {
Log(msg string)
}
type ConsoleLogger struct {
level string
}
func NewConsoleLogger(config *Config) Logger {
return &ConsoleLogger{level: config.LogLevel}
}
func (l *ConsoleLogger) Log(msg string) {
fmt.Printf("[%s] %s\n", l.level, msg)
}
// 服务
type UserService struct {
db *Database
logger Logger
}
func NewUserService(db *Database, logger Logger) *UserService {
return &UserService{db: db, logger: logger}
}
func (s *UserService) GetUser(id int) string {
s.logger.Log(fmt.Sprintf("Fetching user %d", id))
return s.db.Query()
}
func main() {
// 创建容器
ctr := kinit.NewContainer()
// 注册配置(单例)
ctr.MustProvide(func() *Config {
return &Config{
DBConnString: "user:pass@localhost:5432/db",
LogLevel: "info",
}
}, kinit.Singleton())
// 注册数据库(单例)
ctr.MustProvide(NewDatabase, kinit.Singleton())
// 注册日志
ctr.MustProvide(NewConsoleLogger)
// 注册服务
ctr.MustProvide(NewUserService)
// 使用服务
err := ctr.Invoke(func(service *UserService) {
result := service.GetUser(1)
fmt.Println("Result:", result)
})
if err != nil {
panic(err)
}
// 输出:
// [info] Fetching user 1
// Result: query result
}
Kinit 提供了简洁而强大的依赖注入功能,能够帮助你构建松耦合、可测试的应用程序。通过合理使用依赖注入,你可以更容易地管理复杂的依赖关系,并提高代码的可维护性。