简介
之前的一篇文章Go 每日一库之 dig介绍了 uber 开源的依赖注入框架dig
。读了这篇文章后,@overtalk推荐了 Google 开源的wire
工具。所以就有了今天这篇文章,感谢推荐👍
wire
是 Google 开源的一个依赖注入工具。它是一个代码生成器,并不是一个框架。我们只需要在一个特殊的go
文件中告诉wire
类型之间的依赖关系,它会自动帮我们生成代码,帮助我们创建指定类型的对象,并组装它的依赖。
快速使用
先安装工具:
$ go get github.com/google/wire/cmd/wire
上面的命令会在$GOPATH/bin
中生成一个可执行程序wire
,这就是代码生成器。我个人习惯把$GOPATH/bin
加入系统环境变量$PATH
中,所以可直接在命令行中执行wire
命令。
下面我们在一个例子中看看如何使用wire
。
现在,我们来到一个黑暗的世界,这个世界中有一个邪恶的怪兽。我们用下面的结构表示,同时编写一个创建方法:
type Monster struct {
Name string
}
func NewMonster() Monster {
return Monster{Name: "kitty"}
}
有怪兽肯定就有勇士,结构如下,同样地它也有创建方法:
type Player struct {
Name string
}
func NewPlayer(name string) Player {
return Player{Name: name}
}
终于有一天,勇士完成了他的使命,战胜了怪兽:
type Mission struct {
Player Player
Monster Monster
}
func NewMission(p Player, m Monster) Mission {
return Mission{p, m}
}
func (m Mission) Start() {
fmt.Printf("%s defeats %s, world peace!\n", m.Player.Name, m.Monster.Name)
}
这可能是某个游戏里面的场景哈,我们看如何将上面的结构组装起来放在一个应用程序中:
func main() {
monster := NewMonster()
player := NewPlayer("dj")
mission := NewMission(player, monster)
mission.Start()
}
代码量少,结构不复杂的情况下,上面的实现方式确实没什么问题。但是项目庞大到一定程度,结构之间的关系变得非常复杂的时候,这种手动创建每个依赖,然后将它们组装起来的方式就会变得异常繁琐,并且容易出错。这个时候勇士wire
出现了!
wire
的要求很简单,新建一个wire.go
文件(文件名可以随意),创建我们的初始化函数。比如,我们要创建并初始化一个Mission
对象,我们就可以这样:
//+build wireinject
package main
import "github.com/google/wire"
func InitMission(name string) Mission {
wire.Build(NewMonster, NewPlayer, NewMission)
return Mission{}
}
首先这个函数的返回值就是我们需要创建的对象类型,wire
只需要知道类型,return
后返回什么不重要。然后在函数中,我们调用wire.Build()
将创建Mission
所依赖的类型的构造器传进去。例如,需要调用NewMission()
创建Mission
类型,NewMission()
接受两个参数一个Monster
类型,一个Player
类型。Monster
类型对象需要调用NewMonster()
创建,Player
类型对象需要调用NewPlayer()
创建。所以NewMonster()
和NewPlayer()
我们也需要传给wire
。
文件编写完成之后,执行wire
命令:
$ wire
wire: github.com/darjun/go-d