likes
comments
collection
share

Go实践|项目中使用 IOC-golang

作者站长头像
站长
· 阅读数 10

IOC-Golang

阿里开源了 IOC-golang 框架,它是一种基于 Go 语言的 IoC (Inversion of Control) 框架,它提供了依赖注入 (Dependency Injection) 的实现方式。在开发的过程中经常会使用依赖注入框架可以让我们更好的管理和使用程序中各对象的依赖关系,从而提高代码的可读性和可维护性。

"ioc-golang" 的主要特点包括:

  • 支持基于结构体标签的依赖注入;
  • 提供了多种对象创建方式,包括基于接口实现的创建、函数创建、以及基于结构体类型的创建等;
  • 支持循环依赖的解决方案;
  • 支持多个实例的管理;
  • 提供了基于条件判断的对象创建和依赖注入等功能。

小Demo实践

首先要安装 "ioc-golang" 包,可以使用命令:go get github.com/alibaba/ioc-golang

package main

import (
    "fmt"
    "github.com/alibaba/ioc-golang"
)

type UserService interface {
    GetName() string
}

type UserServiceImpl struct {
    Name string `inject:"name"`
}

func (u *UserServiceImpl) GetName() string {
    return u.Name
}

type UserController struct {
    UserService UserService `inject:"user_service"`
}

func (c *UserController) SayHello() {
    fmt.Printf("Hello, %s!\n", c.UserService.GetName())
}

func main() {
    container := ioc.NewContainer()
    container.Register("name", "Tommy")
    container.Register("user_service", &UserServiceImpl{})

    controller := &UserController{}
    err := container.Inject(controller)
    if err != nil {
        panic(err)
    }

    controller.SayHello()
}

在上面的示例代码中,首先定义 UserService 接口和UserServiceImpl 结构体,后者实现了该接口的 GetName 方法,并使用了 "inject" 标签指定了其依赖项 Name。定义了一个 UserController 结构体,其中包含了一个 UserService 类型的依赖项,并使用了 "inject" 标签指定其依赖项为 user_service。这里就是使用 IOC-Golang 框架基于结构体标签的依赖注入的方式实现注入

使用时只需要创建对象,并注册了 name 和 user_service 两个对象。然后,我们创建了一个 UserController 对象,并通过 container.Inject 方法将其依赖项注入到该对象中。

最后,只需要调用 controller.SayHello() 方法,该方法会输出 "Hello, Tommy!"

依赖注入方式

1. 构造函数注入

构造函数注入是最简单的依赖注入方式,通过将依赖作为参数传递给结构体或函数的构造函数,从而实现依赖注入。例如:

goCopy code
type Database struct {
    // ...
}

type UserService struct {
    db *Database
}

func NewUserService(db *Database) *UserService {
    return &UserService{db: db}
}

在上面的例子中,UserService 结构体依赖于 Database 结构体,通过将 Database 作为参数传递给 NewUserService 函数的构造函数,实现了依赖注入。

2. 属性注入

属性注入通过设置结构体或对象的属性来注入依赖。例如:

type Database struct {
    // ...
}

type UserService struct {
    db *Database
}

func (u *UserService) SetDatabase(db *Database) {
    u.db = db
}

在上面的例子中,UserService 结构体的 db 属性依赖于 Database 结构体,通过 SetDatabase 方法设置属性,实现了依赖注入。

3. 接口注入

接口注入通过将依赖实现一个接口,并将该接口作为结构体或对象的属性或参数,从而实现依赖注入。例如:

type Database interface {
    // ...
}

type MysqlDatabase struct {
    // ...
}

func (d *MysqlDatabase) Query(sql string) {
    // ...
}

type UserService struct {
    db Database
}

func NewUserService(db Database) *UserService {
    return &UserService{db: db}
}

在上面的例子中,Database 接口定义了 Query 方法,MysqlDatabase 结构体实现了该接口,并作为 UserService 结构体的依赖。通过将 MysqlDatabase 作为参数传递给 NewUserService 函数,实现了依赖注入。

4. 服务定位器

服务定位器通过一个中心化的服务定位器来管理依赖。例如:

type Database struct {
    // ...
}

type UserService struct {
    db *Database
}

var locator = map[string]interface{}{
    "db": &Database{},
}

func GetDatabase() *Database {
    return locator["db"].(*Database)
}

func NewUserService() *UserService {
    return &UserService{db: GetDatabase()}
}

在上面的例子中,Database 结构体作为 UserService 结构体的依赖,通过 GetDatabase 函数从服务定位器中获取依赖,实现了依赖注入。

本文正在参加「金石计划」