inject

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2025 License: MIT Imports: 7 Imported by: 0

README

Go-Inject - Enhanced Dependency Injection Framework

Go Version License Tests

Go-Inject 是一个基于 Facebook 的 inject 项目增强的 Go 语言依赖注入框架。它提供了基于反射的依赖注入功能,并在原有基础上增加了深度注入等重要特性。

🚀 主要特性

原有特性(继承自 Facebook inject)
  • 基于反射的依赖注入:自动解析和注入依赖关系
  • 结构体标签支持:使用 inject:"" 标签标记需要注入的字段
  • 命名注入:支持通过名称注入特定实例
  • 私有注入:支持创建私有实例
  • 接口注入:自动匹配实现了接口的类型
  • 内联结构体:支持内联结构体的依赖注入
  • 循环依赖检测:自动检测并报告循环依赖
  • 日志支持:可配置的注入过程日志记录
🆕 增强特性
  • 🎯 深度注入(Deep Injection):自动注入手动创建对象的内部依赖
  • 🔄 递归依赖解析:支持多层嵌套的依赖关系自动解析
  • 🛡️ 增强的错误处理:更详细的错误信息和调试支持
  • 📊 完善的测试覆盖:包含深度注入的完整测试用例

📦 安装

go get github.com/ComingCL/go-inject

🎯 深度注入特性详解

什么是深度注入?

深度注入是本项目相对于原始 Facebook inject 的主要增强功能。它解决了以下场景:

场景描述:当你手动创建了一个对象,该对象内部包含其他需要依赖注入的字段时,传统的依赖注入框架无法处理这种情况。

// 传统方式:无法自动注入 d.A 内部的依赖
d := &Service{
    A: &ComponentA{}, // 手动创建的对象,内部的 C 字段无法被自动注入
}

深度注入解决方案:自动检测并注入手动创建对象的内部依赖。

深度注入工作原理
  1. 自动发现:框架检测到字段中存在手动创建的对象
  2. 自动注册:将发现的对象自动注册到依赖图中
  3. 递归注入:递归地为该对象的所有依赖字段进行注入
  4. 多层支持:支持任意深度的嵌套依赖关系

📚 使用指南

基本用法
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 迁移

如果你正在使用 Facebook 的 inject 包,迁移到 go-inject 非常简单:

  1. 更新导入路径:
// 旧的
import "github.com/facebookgo/inject"

// 新的
import "github.com/ComingCL/go-inject"
  1. 代码无需修改,所有原有功能保持兼容

  2. 可选:利用新的深度注入特性优化你的代码

🤝 贡献指南

我们欢迎社区贡献!请遵循以下步骤:

  1. Fork 本仓库
  2. 创建特性分支 (git checkout -b feature/amazing-feature)
  3. 提交更改 (git commit -m 'Add some amazing feature')
  4. 推送到分支 (git push origin feature/amazing-feature)
  5. 开启 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 项目
  • 感谢所有为本项目做出贡献的开发者

📞 支持

如果你遇到问题或有建议,请:

  1. 查看 examples 目录中的示例
  2. 搜索现有的 Issues
  3. 创建新的 Issue 描述你的问题

🔗 相关链接


Go-Inject - 让依赖注入更简单、更强大! 🚀

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Extract

func Extract(name, tag string) (found bool, value string, err error)

Extract 提取给定名称的引用值,如果找到则返回它。 found布尔值有助于区分默认空字符串的"空且找到"与"空且未找到"的性质。

func Populate

func Populate(values ...interface{}) error

Populate 是一个便捷函数,用于使用给定的不完整对象值填充依赖图

Types

type Container

type Container struct {
	// contains filtered or unexported fields
}

Container IoC容器

func NewContainer

func NewContainer() *Container

NewContainer 创建一个新的IoC容器

func (*Container) Populate

func (c *Container) Populate() error

Populate 为所有bean填充依赖字段。 此函数必须在提供所有bean后调用

func (*Container) ProvideWithName

func (c *Container) ProvideWithName(name string, bean interface{}) error

ProvideWithName 使用指定名称提供bean

func (*Container) Provides

func (c *Container) Provides(beans ...interface{}) error

Provides 使用默认名称提供一些bean

type Graph

type Graph struct {
	Logger Logger // 可选的,将触发信息日志
	// contains filtered or unexported fields
}

func (*Graph) Objects

func (g *Graph) Objects() []*Object

Objects 返回所有已知对象,包括命名的和未命名的。返回的 元素不是稳定顺序的。

func (*Graph) Populate

func (g *Graph) Populate() error

Populate 填充不完整的对象

func (*Graph) Provide

func (g *Graph) Provide(objects ...*Object) error

type Logger

type Logger interface {
	Info(msg string, keysAndValues ...any)
}

type Object

type Object struct {
	Value    interface{}
	Name     string             // 可选的名称
	Complete bool               // 如果为true,该Value将被视为完整的
	Fields   map[string]*Object // 填充已注入的字段名称及其对应的*Object
	// contains filtered or unexported fields
}

Object Graph中的一个对象

func (*Object) String

func (o *Object) String() string

Directories

Path Synopsis
examples
advanced command
basic command
container command
deep-injection command
web-service command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL