共分两篇:
项目地址:github.com/google/wire
简介
wire是 Google 开源的一个依赖注入工具。它是一个代码生成器,并不是一个框架。我们只需要在一个特殊的go文件中告诉wire类型之间的依赖关系,它会自动帮我们生成代码,帮助我们创建指定类型的对象,并组装它的依赖。
使用
1. 简单例子:
一个普通的符合依赖注入设计原理的例子:
package dao
import (
"errors"
"fmt"
"time"
)
type Message string
func NewMessage() Message {
return Message("hi here!")
}
type Greeter struct {
Message Message
}
func NewGreeter(m Message) *Greeter {
return &Greeter{Message: m}
}
func (g *Greeter) Greet() Message {
return g.Message
}
type Event struct {
Greeter *Greeter
}
func NewEvent(greeter *Greeter) *Event {
return &Event{Greeter: greeter}
}
func (e *Event) Start() {
msg := e.Greeter.Greet()
fmt.Println(msg)
}
func main() {
message := NewMessage()
greeter := NewGreeter(message)
event := NewEvent(greeter)
event.Start()
}
依赖注入的缺点是需要很多的初始化步骤。现在,使用wire去自动生成代码:
将main函数改为:
func main() {
event := InitializeEvent()
event.Start()
}
在同目录下,创建wire.go
// +build wireinject
// The build tag makes sure the stub is not built in the final build.
package main
import (
"github.com/google/wire"
)
//go:generate
func InitializeEvent() *Event {
wire.Build(NewEvent, NewGreeter, NewMessage)
return nil
}
在目录下,使用命令行工具,执行 wire 命令
luslin@local:~/go/src/github.com/luslin/tools/wire_test/dao$ wire
wire: github.com/luslin/tools/wire_test/dao: wrote /home/luslin/go/src/github.com/luslin/tools/wire_test/dao/wire_gen.go
就会生成wire_gen.go 文件, 内容为:
// Code generated by Wire. DO NOT EDIT.
//go:generate wire
//+build !wireinject
package main
// Injectors from wire.go:
func InitializeEvent() *Event {
message := NewMessage()
greeter := NewGreeter(message)
event := NewEvent(greeter)
return event
}
2. 构造函数中传入参数,并返回错误
在Greeter结构体中,加入了Grumy变量,并根据时间设置其值。
在创建Event时,则根据Grumy报错
package main
import (
"errors"
"fmt"
"time"
)
type Message string
func NewMessage(phrase string) Message {
return Message(phrase)
}
type Greeter struct {
Message Message
Grumy bool
}
func NewGreeter(m Message) *Greeter {
var grumpy bool
if time.Now().Unix()%2 == 0 {
grumpy = true
}
return &Greeter{Message: m, Grumy: grumpy}
}
func (g *Greeter) Greet() Message {
if g.Grumy {
return Message("Go away")
}
return g.Message
}
type Event struct {
Greeter *Greeter
}
func NewEvent(greeter *Greeter) (*Event, error) {
if greeter.Grumy {
return &Event{}, errors.New("gruny is true")
}
return &Event{Greeter: greeter},nil
}
func (e *Event) Start() {
msg := e.Greeter.Greet()
fmt.Println(msg)
}
func main() {
event, err := InitializeEvent("test")
if err != nil {
panic(err)
}
event.Start()
}
wire.go 则变成:
func InitializeEvent(phrase string) (*Event, error) {
wire.Build(NewEvent, NewGreeter, NewMessage)
return nil, nil
}
生成的文件 wire_gen.go:
func InitializeEvent(phrase string) (*Event, error) {
message := NewMessage(phrase)
greeter := NewGreeter(message)
event, err := NewEvent(greeter)
if err != nil {
return nil, err
}
return event, nil
}
``