golang轻量级通用依赖注入容器插件库ore的使用

Golang轻量级通用依赖注入容器插件库Ore的使用

Ore是一个强大且灵活的Go语言依赖注入(DI)库,旨在简化复杂应用程序结构,同时保持性能和模块化。

ore

主要特性

1. 灵活的生命周期管理

  • 单例(Singletons): 生命周期贯穿整个应用程序
  • 作用域(Scoped): 生命周期绑定到特定上下文
  • 瞬时(Transient): 每次解析时创建新实例

2. 别名支持

  • 将多个实现链接到同一接口
  • 轻松解析首选实现或检索所有注册选项

3. 优雅终止

  • 应用程序终止: 按正确依赖顺序关闭所有已解析的单例(实现Shutdowner接口)
  • 上下文终止: 当上下文结束时释放所有已解析的作用域实例(实现Disposer接口)

4. 占位符注册

  • 在应用程序设置时注册不完整的依赖项
  • 在请求或事件发生时动态提供运行时值

5. 多容器(模块)

  • 为模块化应用程序创建隔离的依赖关系图
  • 通过为每个容器分离服务注册和解析来强制模块边界

安装

go get -u github.com/firasdarwish/ore

快速示例

package main

import (
  "context"
  "fmt"
  "github.com/firasdarwish/ore"
)

// 定义一个服务
type MyService struct {
  Message string
}

func main() {
  // 注册一个单例服务
  ore.RegisterSingleton[SomeServiceInterface](&MyService{Message: "Hello, Ore!"})
  
  // 解析服务
  service, _ := ore.Get[*SomeServiceInterface](context.Background())
  fmt.Println(service.Message) // 输出: Hello, Ore!
}

完整示例

下面是一个更完整的示例,展示Ore的主要功能:

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/firasdarwish/ore"
)

// 定义接口
type Greeter interface {
	Greet() string
}

// 实现接口
type EnglishGreeter struct{}

func (g *EnglishGreeter) Greet() string {
	return "Hello, World!"
}

type ChineseGreeter struct{}

func (g *ChineseGreeter) Greet() string {
	return "你好,世界!"
}

// 需要注入的服务
type App struct {
	greeter Greeter `ore:"inject"`
}

func (a *App) Run() {
	fmt.Println(a.greeter.Greet())
}

func main() {
	// 创建容器
	container := ore.NewContainer()

	// 注册服务(使用别名)
	container.RegisterSingleton[Greeter](&EnglishGreeter{}, ore.WithAlias("en"))
	container.RegisterSingleton[Greeter](&ChineseGreeter{}, ore.WithAlias("zh"))

	// 注册应用服务
	container.RegisterTransient(func(g Greeter) *App {
		return &App{greeter: g}
	})

	// 创建上下文
	ctx := context.Background()

	// 解析特定语言的greeter
	enGreeter, err := container.GetTagged[Greeter](ctx, "en")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(enGreeter.Greet()) // 输出: Hello, World!

	zhGreeter, err := container.GetTagged[Greeter](ctx, "zh")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(zhGreeter.Greet()) // 输出: 你好,世界!

	// 解析App并运行
	app, err := container.Get[*App](ctx)
	if err != nil {
		log.Fatal(err)
	}
	app.Run() // 默认使用最后注册的Greeter实现
}

生命周期管理示例

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/firasdarwish/ore"
)

type Database struct {
	conn string
}

func (db *Database) Connect() {
	fmt.Println("Connecting to database:", db.conn)
}

func (db *Database) Disconnect() {
	fmt.Println("Disconnecting from database:", db.conn)
}

func (db *Database) Dispose() {
	db.Disconnect()
}

func main() {
	container := ore.NewContainer()

	// 注册单例服务
	container.RegisterSingleton(func() *Database {
		return &Database{conn: "singleton-connection"}
	})

	// 注册作用域服务
	container.RegisterScoped(func() *Database {
		return &Database{conn: "scoped-connection"}
	})

	// 注册瞬时服务
	container.RegisterTransient(func() *Database {
		return &Database{conn: "transient-connection"}
	})

	// 创建上下文
	ctx := context.Background()

	// 解析单例(多次解析返回同一实例)
	db1, _ := container.Get[*Database](ctx)
	db2, _ := container.Get[*Database](ctx)
	fmt.Println("Singleton equal:", db1 == db2) // true

	// 创建作用域上下文
	scopedCtx, dispose := ore.WithScope(ctx)
	defer dispose()

	// 解析作用域服务(同一作用域内返回同一实例)
	db3, _ := container.Get[*Database](scopedCtx)
	db4, _ := container.Get[*Database](scopedCtx)
	fmt.Println("Scoped equal:", db3 == db4) // true

	// 解析瞬时服务(每次返回新实例)
	db5, _ := container.Get[*Database](scopedCtx)
	db6, _ := container.Get[*Database](scopedCtx)
	fmt.Println("Transient equal:", db5 == db6) // false
}

Ore提供了强大的依赖注入功能,可以帮助您构建更模块化、更易测试的Go应用程序。


更多关于golang轻量级通用依赖注入容器插件库ore的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang轻量级通用依赖注入容器插件库ore的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang轻量级依赖注入容器ore使用指南

ore是一个轻量级的Go语言依赖注入容器库,它提供了简单易用的依赖注入功能,适合中小型项目使用。下面我将详细介绍ore的使用方法。

安装

go get github.com/hex-techs/ore

基本用法

1. 容器初始化

import "github.com/hex-techs/ore"

func main() {
    // 创建一个新的容器
    c := ore.NewContainer()
    
    // 或者使用单例容器
    ore.Singleton(func() *Service {
        return &Service{}
    })
}

2. 注册服务

ore支持三种注册方式:

// 1. 注册单例
ore.Singleton(func() *Database {
    return &Database{URL: "localhost:5432"}
})

// 2. 注册瞬态实例(每次获取都是新实例)
ore.Transient(func() *Logger {
    return &Logger{}
})

// 3. 注册实例(直接注册已存在的实例)
db := &Database{URL: "production-db"}
ore.Instance(db)

3. 获取服务

// 通过类型获取
var db *Database
ore.Resolve(&db)

// 通过接口获取
var logger LoggerInterface
ore.Resolve(&logger)

// 使用MustResolve(如果服务未注册会panic)
svc := ore.MustResolve[*Service]()

4. 构造函数注入

type UserService struct {
    db     *Database
    logger *Logger
}

// 使用ore标签标记需要注入的字段
type UserService struct {
    db     *Database `ore:"inject"`
    logger *Logger   `ore:"inject"`
}

// 或者使用构造函数
func NewUserService(db *Database, logger *Logger) *UserService {
    return &UserService{db: db, logger: logger}
}

// 注册时
ore.Singleton(NewUserService)

高级用法

1. 命名服务

// 注册命名服务
ore.SingletonNamed("mysql", func() *Database {
    return &Database{Driver: "mysql"}
})

ore.SingletonNamed("postgres", func() *Database {
    return &Database{Driver: "postgres"}
})

// 获取命名服务
var db *Database
ore.ResolveNamed("mysql", &db)

2. 生命周期管理

type Resource struct {
    // ...
}

func (r *Resource) Close() error {
    // 清理资源
    return nil
}

// 注册实现了io.Closer的服务
ore.Singleton(func() *Resource {
    return &Resource{}
})

// 容器关闭时会自动调用Close()
defer c.Close()

3. 模块化注册

type DatabaseModule struct{}

func (m *DatabaseModule) Configure(c *ore.Container) {
    c.Singleton(func() *Database {
        return &Database{URL: "localhost:5432"}
    })
}

type LoggerModule struct{}

func (m *LoggerModule) Configure(c *ore.Container) {
    c.Singleton(func() *Logger {
        return &Logger{Level: "info"}
    })
}

// 注册模块
c := ore.NewContainer()
c.Configure(&DatabaseModule{}, &LoggerModule{})

完整示例

package main

import (
	"fmt"
	"github.com/hex-techs/ore"
)

// 定义服务接口
type Logger interface {
	Log(message string)
}

// 实现服务
type ConsoleLogger struct{}

func (l *ConsoleLogger) Log(message string) {
	fmt.Println(message)
}

// 数据库服务
type Database struct {
	URL string
}

func (d *Database) Query() string {
	return "Data from " + d.URL
}

// 用户服务
type UserService struct {
	db     *Database `ore:"inject"`
	logger Logger    `ore:"inject"`
}

func (s *UserService) GetUser(id int) {
	s.logger.Log(fmt.Sprintf("Getting user %d", id))
	data := s.db.Query()
	s.logger.Log(fmt.Sprintf("Got data: %s", data))
}

func main() {
	// 注册服务
	ore.Singleton(func() *Database {
		return &Database{URL: "localhost:5432"}
	})
	
	ore.Singleton(func() Logger {
		return &ConsoleLogger{}
	})
	
	ore.Singleton(func(us *UserService) *UserService {
		return us
	})
	
	// 获取用户服务
	userService := ore.MustResolve[*UserService]()
	userService.GetUser(1)
	
	// 输出:
	// Getting user 1
	// Data from localhost:5432
}

注意事项

  1. ore是线程安全的,可以在并发环境下使用
  2. 循环依赖会导致panic,需要设计时避免
  3. 推荐使用接口而不是具体类型注册服务
  4. 对于大型项目,可以考虑更成熟的DI框架如wire或dig

ore以其简单性和轻量级特性,非常适合中小型Go项目快速实现依赖注入,减少了手动管理依赖的复杂度。

回到顶部