di7/diGo语言终极依赖注入容器详解让你的代码更解耦、更灵活【免费下载链接】diDependency injection container in go (golang)项目地址: https://gitcode.com/gh_mirrors/di7/didi7/di 是一个专为 Go 语言设计的依赖注入容器框架它能够高效管理应用程序中对象的生命周期自动创建对象、解析依赖关系并在对象不再使用时妥善关闭它们。作为一款专注于性能的依赖注入工具di7/di 可以帮助开发者构建更解耦、更灵活且易于维护的 Go 应用程序。为什么选择依赖注入容器依赖注入Dependency Injection是一种重要的软件设计模式它通过将对象的创建和依赖解析过程与业务逻辑分离带来了诸多好处降低耦合度组件之间不再直接创建依赖对象而是通过容器获取减少了代码间的直接关联提高可测试性可以轻松替换依赖对象为模拟实现便于单元测试简化代码维护对象的创建和配置集中管理修改时无需遍历所有使用处增强代码灵活性通过配置即可改变对象的实现方式无需修改业务逻辑代码如果你还不确定依赖注入是否能改善你的应用可以了解更多关于依赖注入和依赖注入容器的知识。快速上手di7/di 基本使用使用 di7/di 只需几个简单步骤即可实现对象的依赖管理。定义对象首先你需要为要管理的对象创建一个定义Definition。定义至少包含一个Build函数用于创建对象实例MyObjectDef : di.Def{ Build: func(ctn di.Container) (interface{}, error) { return MyObject{}, nil }, } // 可选为定义设置名称和类型便于检索 MyObjectDef.SetName(my-object) MyObjectDef.SetIs((*MyObject)(nil))创建构建器接下来使用NewEnhancedBuilder创建一个增强型构建器这是推荐的使用方式builder, err : di.NewEnhancedBuilder()添加定义到构建器将之前创建的对象定义添加到构建器中err builder.Add(MyObjectDef)构建容器调用构建器的Build方法生成容器ctn, err : builder.Build()从容器中获取对象现在你可以从容器中检索对象了。di7/di 提供了多种检索方式// 通过定义获取推荐性能最优 ctn.Get(MyObjectDef).(*MyObject) // 通过名称获取稍慢但更灵活 ctn.Get(my-object).(*MyObject) // 通过类型获取较慢需使用反射 ctn.Get(reflect.TypeOf((*MyObject)(nil))).(*MyObject)容器默认采用单例模式第一次调用Get方法时创建对象之后的调用会返回同一个实例除非将定义的Unshared字段设置为true。深入理解di7/di 核心功能定义Definitions详解定义是 di7/di 的核心概念它描述了如何创建和管理对象。除了基本的Build函数外定义还支持多种高级特性依赖解析Build函数可以使用容器来解析依赖关系实现对象间的自动装配MyObjectWithDependencyDef : di.NewDef(func(ctn di.Container) (interface{}, error) { return MyObjectWithDependency{ Object: ctn.Get(MyObjectDef).(*MyObject), }, nil })生命周期管理通过Close函数你可以定义对象的清理逻辑当容器被删除时会自动调用这些清理函数di.Def{ Build: func(ctn di.Container) (interface{}, error) { return MyObject{}, nil }, Close: func(obj interface{}) error { // 假设 MyObject 有一个 Close 方法 return obj.(*MyObject).Close() }, }非共享对象默认情况下容器会缓存对象实例。如果需要每次获取新实例可以将Unshared设为trueMyObjectDef di.Def{ Unshared: true, // 每次调用 Get 都会创建新实例 Build: func(ctn di.Container) (interface{}, error) { return MyObject{}, nil }, }作用域Scopes管理对象生命周期作用域是 di7/di 中另一个强大的特性特别适用于请求式应用如 Web 应用。通过作用域你可以控制对象的生命周期范围。di7/di 默认提供三个作用域App应用级、Request请求级和SubRequest子请求级按从通用到具体的顺序排列。// 创建具有默认作用域的构建器 builder, err : di.NewEnhancedBuilder() // 定义一个应用级对象 AppDef : di.Def{ Scope: di.App, // 可选默认即为 App 作用域 Build: func(ctn di.Container) (interface{}, error) { return MyObject{}, nil }, } // 定义一个请求级对象 RequestDef : di.Def{ Scope: di.Request, Build: func(ctn di.Container) (interface{}, error) { return MyObject{}, nil }, }容器可以创建子容器来管理更具体作用域的对象// 构建应用级容器 app, err : builder.Build() // 创建请求级子容器 req1, err : app.SubContainer() req2, err : app.SubContainer()应用级对象在所有子容器中共享而请求级对象则每个请求容器都有自己的实例// 应用级对象所有容器获取的是同一个实例 o1 : app.Get(AppDef).(*MyObject) o2 : req1.Get(AppDef).(*MyObject) o3 : req2.Get(AppDef).(*MyObject) // o1 o2 o3 // 请求级对象每个请求容器有自己的实例 o4 : req1.Get(RequestDef).(*MyObject) o5 : req2.Get(RequestDef).(*MyObject) // o4 ! o5对象检索的三种方式di7/di 提供了三种从容器中检索对象的方法适用于不同场景Get 方法Get方法是最常用的检索方式如果对象无法创建它会直接 panico1 : ctn.Get(MyObjectDef).(*MyObject)SafeGet 方法SafeGet方法与Get类似但不会 panic而是返回错误objectInterface, err : ctn.SafeGet(MyObjectDef) object, ok : objectInterface.(*MyObject)Fill 方法Fill方法使用反射来填充提供的对象指针同样返回错误var object *MyObject err : ctn.Fill(MyObjectDef, object)Web 应用集成HTTP 辅助工具di7/di 提供了方便的 HTTP 中间件简化在 Web 应用中的使用// 创建应用容器 builder, err : di.NewEnhancedBuilder() err builder.Add(/* 定义 */) app, err : builder.Build() // 使用 HTTP 中间件 handlerWithDiMiddleware : di.HTTPMiddleware(handler, app, func(msg string) { logger.Error(msg) // 错误日志处理 })在请求处理函数中可以轻松获取请求级容器handler : func(w http.ResponseWriter, r *http.Request) { // 获取请求容器 ctn : di.C(r) obj : ctn.Get(object).(*MyObject) // 或者使用快捷方式 obj : di.Get(r, object).(*MyObject) }性能优化让依赖注入更高效虽然依赖注入会带来一些性能开销但 di7/di 已经做了很多优化同时你也可以通过以下方式进一步提升性能选择合适的检索方式性能从高到低排序通过定义检索 通过名称检索 通过类型检索。在性能关键路径上优先使用定义检索。预加载共享对象共享对象的第一次检索会有互斥锁开销可以在应用启动阶段预加载这些对象// 应用启动时预加载关键对象 app.Get(MyCriticalObjectDef)避免非共享对象的 Close 函数非共享对象如果定义了Close函数容器需要跟踪它们这会增加开销。如果可能避免为非共享对象定义Close函数。实际示例数据库连接管理下面是一个使用 di7/di 管理数据库连接的示例展示了如何在实际项目中应用依赖注入// 定义数据库连接池应用级 var MysqlPoolDef di.Def{ Name: mysql-pool, Scope: di.App, Build: func(ctn di.Container) (interface{}, error) { db, err : sql.Open(mysql, user:password/) db.SetMaxOpenConns(1) return db, err }, Close: func(obj interface{}) error { return obj.(*sql.DB).Close() }, } // 定义数据库连接请求级 var MySqlDef di.Def{ Name: mysql, Scope: di.Request, Build: func(ctn di.Container) (interface{}, error) { pool : ctn.Get(mysql-pool).(*sql.DB) return pool.Conn(context.Background()) }, Close: func(obj interface{}) error { return obj.(*sql.Conn).Close() }, } func main() { builder, _ : di.NewEnhancedBuilder() builder.Add(MysqlPoolDef) builder.Add(MySqlDef) app, _ : builder.Build() defer app.Delete() http.HandleFunc(/, func(w http.ResponseWriter, r *http.Request) { // 创建请求容器并在请求结束时删除 request, _ : app.SubContainer() defer request.Delete() handler(w, r, request) }) http.ListenAndServe(:8080, nil) }在这个示例中数据库连接池是应用级别的单例而每个请求会获取自己的数据库连接请求结束时自动关闭连接既保证了连接的高效利用又简化了资源管理。总结提升 Go 项目质量的得力助手di7/di 作为一个功能强大的依赖注入容器为 Go 项目提供了优雅的依赖管理解决方案。通过使用 di7/di你可以编写更清晰、更解耦的代码简化对象生命周期管理提高代码可测试性和可维护性轻松应对复杂的依赖关系无论是小型工具还是大型应用di7/di 都能帮助你构建更专业、更高质量的 Go 程序。要开始使用 di7/di只需通过以下命令克隆仓库git clone https://gitcode.com/gh_mirrors/di7/di然后参考项目中的示例代码和文档快速将依赖注入集成到你的项目中。【免费下载链接】diDependency injection container in go (golang)项目地址: https://gitcode.com/gh_mirrors/di7/di创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考