依赖注入
往往我们创建一个A对象时,需要依赖B对象,然后B对象可能又依赖于C对象,导致我们创建A对象时,需要初始化好B对象和C对象。当随着我们的项目的复杂度升级或是对象依赖关系复杂时,手动创建对象变得繁琐,这时便需要依赖注入来帮助我们管理好对象的依赖关系。
wire 工具
Go Cloud团队开发,主要有两个核心概念:Provider和Injector
Provider: 用来指定单个对象的创建
Injector: 有wire工具组织对象的依赖关系,做具体对象的创建工作
安装:
go install github.com/google/wire/cmd/wire@latest
教程
-
创建一个greeter.go的文件
里面创建了Message、Greeter、Event三个结构体。 添加Provider:NewMessage、NewGreeter和NewEvent
-
创建一个wire.go的文件
里面使用wire工具来指定Injector,使用了wire.Build,该函数内的参数为Provider(没有顺序要求)
-
在同级目录下运行命令
wire
代码
greeter.go
type Message string
type Greeter struct {
Grumpy bool
Message Message
}
type Event struct {
Greeter Greeter
}
func NewMessage() Message {
return Message("Hi there!")
}
func NewGreeter(m Message) Greeter {
var grumpy bool
if time.Now().Unix()%2 == 0 {
grumpy = true
}
return Greeter{Message: m, Grumpy: grumpy}
}
func (g Greeter) Greet() Message {
if g.Grumpy {
return Message("go away!")
}
return g.Message
}
func NewEvent(g Greeter) (Event, error) {
if g.Grumpy {
return Event{}, errors.New("could not create event: event greeter is grumpy")
}
return Event{Greeter: g}, nil
}
func (e Event) Start() {
msg := e.Greeter.Greet()
fmt.Println(msg)
}
wire.go
// 将一组 Provider 打包
var eventSet = wire.NewSet(NewGreeter, NewMessage)
func InitializeEvent() (Event, error) {
wire.Build(NewEvent, eventSet)
return Event{}, nil
}
func main() {
e, _ := InitializeEvent()
e.Start()
}
wire_gen.go 为自动生成的代码
//go:generate go run github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject
package main
import (
"github.com/google/wire"
)
// Injectors from wire.go:
func InitializeEvent() (Event, error) {
message := NewMessage()
greeter := NewGreeter(message)
event, err := NewEvent(greeter)
if err != nil {
return Event{}, err
}
return event, nil
}
// wire.go:
var eventSet = wire.NewSet(NewGreeter, NewMessage)
func main() {
e, _ := InitializeEvent()
e.Start()
}
解释
+build tags 用于go build 条件编译用的, 如:+build !wireinject , 表示没有 wireinject 这个tag时 编译这个文件