简介
今天我们来介绍 Go 语言的一个依赖注入(DI)库——dig。dig 是 uber 开源的库。Java 依赖注入的库有很多,相信即使不是做 Java 开发的童鞋也听过大名鼎鼎的 Spring。相比庞大的 Spring,dig 很小巧,实现和使用都比较简洁。
快速使用
第三方库需要先安装,由于我们的示例中使用了前面介绍的go-ini和go-flags,这两个库也需要安装:
$ go get go.uber.org/dig
$ go get gopkg.in/ini.v1
$ go get github.com/jessevdk/go-flags
下面看看如何使用:
package main
import (
"fmt"
"github.com/jessevdk/go-flags"
"go.uber.org/dig"
"gopkg.in/ini.v1"
)
type Option struct {
ConfigFile string `short:"c" long:"config" description:"Name of config file."`
}
func InitOption() (*Option, error) {
var opt Option
_, err := flags.Parse(&opt)
return &opt, err
}
func InitConf(opt *Option) (*ini.File, error) {
cfg, err := ini.Load(opt.ConfigFile)
return cfg, err
}
func PrintInfo(cfg *ini.File) {
fmt.Println("App Name:", cfg.Section("").Key("app_name").String())
fmt.Println("Log Level:", cfg.Section("").Key("log_level").String())
}
func main() {
container := dig.New()
container.Provide(InitOption)
container.Provide(InitConf)
container.Invoke(PrintInfo)
}
在同一目录下创建配置文件my.ini
:
app_name = awesome web
log_level = DEBUG
[mysql]
ip = 127.0.0.1
port = 3306
user = dj
password = 123456
database = awesome
[redis]
ip = 127.0.0.1
port = 6381
运行程序,输出:
$ go run main.go -c=my.ini
App Name: awesome web
Log Level: DEBUG
dig
库帮助开发者管理这些对象的创建和维护,每种类型的对象会创建且只创建一次。dig
库使用的一般流程:
- 创建一个容器:
dig.New
; - 为想要让
dig
容器管理的类型创建构造函数,构造函数可以返回多个值,这些值都会被容器管理; - 使用这些类型的时候直接编写一个函数,将这些类型作为参数,然后使用
container.Invoke
执行我们编写的函数。
参数对象
有时候,创建对象有很多依赖,或者编写函数时有多个参数依赖。如果将这些依赖都作为参数传入,那么代码将变得非常难以阅读:
container.Provide(func (arg1 *Arg1, arg2 *Arg2, arg3 *Arg3, ....) {
// ...
})
dig
支持将所有参数打包进一个对象中,唯一需要的就是将dig.In
内嵌到该类型中:
type Params {
dig.In
Arg1 *Arg1
Arg2 *Arg2
Arg3 *Arg3
Arg4 *Arg4
}
container.Provide(func (params Params) *Object {
// ...
})
内嵌了dig.In
之后,dig
会将该类型中的其它字段看成Object
的依赖,创建Object
类型的对象时,会先将依赖的Arg1/Arg2/Arg3/Arg4
创建好。
package main
import (
"fmt"
"log"
"github.com/jessevdk/go-flags"
"go.uber.org/dig"
"gopkg.in/ini.v1"
)
type Option struct {
ConfigFile string `short:"c" long:"config" description:"Name of config file."`
}
type RedisConfig struct {
IP string
Port int
DB int
}
type MySQLConfig struct {
IP string
Port int
User string
Password string
Database string
}
type Config struct {