Go-Inject 是一个基于 Facebook 的 inject 项目增强的 Go 语言依赖注入框架。它提供了基于反射的依赖注入功能,并在原有基础上增加了深度注入等重要特性。
- ✅ 基于反射的依赖注入:自动解析和注入依赖关系
- ✅ 结构体标签支持:使用
inject:""标签标记需要注入的字段 - ✅ 命名注入:支持通过名称注入特定实例
- ✅ 私有注入:支持创建私有实例
- ✅ 接口注入:自动匹配实现了接口的类型
- ✅ 内联结构体:支持内联结构体的依赖注入
- ✅ 循环依赖检测:自动检测并报告循环依赖
- ✅ 日志支持:可配置的注入过程日志记录
- 🎯 深度注入(Deep Injection):自动注入手动创建对象的内部依赖
- 🔄 递归依赖解析:支持多层嵌套的依赖关系自动解析
- 🛡️ 增强的错误处理:更详细的错误信息和调试支持
- 📊 完善的测试覆盖:包含深度注入的完整测试用例
go get github.com/ComingCL/go-inject深度注入是本项目相对于原始 Facebook inject 的主要增强功能。它解决了以下场景:
场景描述:当你手动创建了一个对象,该对象内部包含其他需要依赖注入的字段时,传统的依赖注入框架无法处理这种情况。
// 传统方式:无法自动注入 d.A 内部的依赖
d := &Service{
A: &ComponentA{}, // 手动创建的对象,内部的 C 字段无法被自动注入
}深度注入解决方案:自动检测并注入手动创建对象的内部依赖。
- 自动发现:框架检测到字段中存在手动创建的对象
- 自动注册:将发现的对象自动注册到依赖图中
- 递归注入:递归地为该对象的所有依赖字段进行注入
- 多层支持:支持任意深度的嵌套依赖关系
package main
import (
"fmt"
"github.com/ComingCL/go-inject"
)
// 定义服务接口
type Logger interface {
Log(message string)
}
// 实现日志服务
type ConsoleLogger struct{}
func (c *ConsoleLogger) Log(message string) {
fmt.Println("LOG:", message)
}
// 定义数据库服务
type Database struct {
Logger Logger `inject:""`
}
func (d *Database) Query(sql string) {
d.Logger.Log("Executing: " + sql)
}
// 定义用户服务
type UserService struct {
DB *Database `inject:""`
Logger Logger `inject:""`
}
func (u *UserService) GetUser(id int) {
u.Logger.Log(fmt.Sprintf("Getting user %d", id))
u.DB.Query("SELECT * FROM users WHERE id = ?")
}
func main() {
var g inject.Graph
// 注册依赖
logger := &ConsoleLogger{}
db := &Database{}
userService := &UserService{}
g.Provide(&inject.Object{Value: logger})
g.Provide(&inject.Object{Value: db})
g.Provide(&inject.Object{Value: userService})
// 执行依赖注入
if err := g.Populate(); err != nil {
panic(err)
}
// 使用服务
userService.GetUser(123)
}package main
import (
"fmt"
"github.com/ComingCL/go-inject"
)
type ComponentA struct {
C *ComponentC `inject:""`
}
type ComponentB struct{}
type ComponentC struct {
B *ComponentB `inject:""`
}
type Service struct {
A *ComponentA `inject:""`
}
func main() {
var g inject.Graph
// 注册基础依赖
b := &ComponentB{}
c := &ComponentC{}
// 创建包含手动实例的服务
service := &Service{
A: &ComponentA{}, // 手动创建的实例
}
g.Provide(&inject.Object{Value: b})
g.Provide(&inject.Object{Value: c})
g.Provide(&inject.Object{Value: service})
// 执行依赖注入(包括深度注入)
if err := g.Populate(); err != nil {
panic(err)
}
// 验证深度注入结果
fmt.Printf("service.A.C != nil: %v\n", service.A.C != nil) // true
fmt.Printf("service.A.C.B != nil: %v\n", service.A.C.B != nil) // true
fmt.Printf("service.A.C.B == b: %v\n", service.A.C.B == b) // true
}type Config struct {
DatabaseURL string
RedisURL string
}
type Service struct {
MainDB *Database `inject:"main_db"`
CacheDB *Database `inject:"cache_db"`
}
func main() {
var g inject.Graph
mainDB := &Database{URL: "postgres://main"}
cacheDB := &Database{URL: "redis://cache"}
service := &Service{}
g.Provide(&inject.Object{Value: mainDB, Name: "main_db"})
g.Provide(&inject.Object{Value: cacheDB, Name: "cache_db"})
g.Provide(&inject.Object{Value: service})
g.Populate()
}type Service struct {
Logger Logger `inject:"private"` // 创建私有实例
}go-inject/
├── README.md # 项目文档
├── LICENSE # MIT 许可证
├── go.mod # Go 模块文件
├── inject.go # 核心注入逻辑
├── inject_test.go # 测试用例
├── structtag.go # 结构体标签解析
├── structtag_test.go # 标签解析测试
├── ioc_container.go # IoC 容器实现
└── examples/ # 使用示例
├── basic/ # 基础用法示例
├── deep-injection/ # 深度注入示例
├── web-service/ # Web 服务示例
└── advanced/ # 高级用法示例
运行所有测试:
go test -v运行特定测试:
go test -run TestForDeepInject -v查看测试覆盖率:
go test -cover| 特性 | Facebook inject | Go-Inject |
|---|---|---|
| 基础注入 | ✅ | ✅ |
| 深度注入 | ❌ | ✅ |
| 递归依赖 | 部分支持 | ✅ 完全支持 |
| 错误处理 | 基础 | 增强 |
| 测试覆盖 | 基础 | 完整 |
如果你正在使用 Facebook 的 inject 包,迁移到 go-inject 非常简单:
- 更新导入路径:
// 旧的
import "github.com/facebookgo/inject"
// 新的
import "github.com/ComingCL/go-inject"-
代码无需修改,所有原有功能保持兼容
-
可选:利用新的深度注入特性优化你的代码
我们欢迎社区贡献!请遵循以下步骤:
- Fork 本仓库
- 创建特性分支 (
git checkout -b feature/amazing-feature) - 提交更改 (
git commit -m 'Add some amazing feature') - 推送到分支 (
git push origin feature/amazing-feature) - 开启 Pull Request
# 克隆仓库
git clone https://github.com/ComingCL/go-inject.git
cd go-inject
# 运行测试
go test -v
# 检查代码格式
go fmt ./...
# 运行静态分析
go vet ./...本项目基于 MIT 许可证开源。详见 LICENSE 文件。
- 感谢 Facebook 团队开源的原始 inject 项目
- 感谢所有为本项目做出贡献的开发者
如果你遇到问题或有建议,请:
Go-Inject - 让依赖注入更简单、更强大! 🚀