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 函数从服务定位器中获取依靠,完成了依靠注入。

本文正在参加「金石方案」