wire执行过程:
一.假设需要定义多个有依赖的启动项(代码如下)
package main
import ("fmt")
type Message string
func NewMessage() Message {
return Message("Hi there!")
}
type Event struct {
Greeter Greeter // <- adding a Greeter field
}
func NewEvent(g Greeter) Event {
return Event{Greeter: g}
}
func (e Event) Start() {
msg := e.Greeter.Greet()
fmt.Println(msg)
}
func NewGreeter(m Message) Greeter {
return Greeter{Message: m}
}
type Greeter struct {
Message Message // <- adding a Message field
}
func (g Greeter) Greet() Message {
return g.Message
}
func main() {
// message := NewMessage()
// greeter := NewGreeter(message)
// event := NewEvent(greeter)
// event.Start()
//如果没依赖注入,就需要写上面这些代码,现在用一个 InitializeEvent 方法包含这些,而这个方法让他自动生成
e := InitializeEvent()
e.Start()
}
二。新建一个 wire.go 文件,名称不一定用这个,但是为了规范和约束,一般都用这个。内容如下。
//go:build wireinject
// +build wireinject
package main
import "github.com/google/wire"
func InitializeEvent() Event {
wire.Build(NewEvent, NewGreeter, NewMessage)
return Event{}
}
//这个是简写,直接用 panic 包裹起来即可,因为不需要检查,所以不需要反馈
// func InitializeEvent() Event {
// panic(wire.Build(NewEvent, NewMessage, NewGreeter))
// }
三。执行 wire 命令,自动生成 wire_gen.go 文件,内容如下:
// Code generated by Wire. DO NOT EDIT.
//go:generate go run github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject
package main
// Injectors from wire.go:
func InitializeEvent() Event {
message := NewMessage()
greeter := NewGreeter(message)
event := NewEvent(greeter)
return event
}
四。结果、自动生成了第一步中繁杂的依赖定义。
五。注意点:
5.1、Injector: 由wire自动生成的函数。
函数内部会按根据依赖顺序调用相关 privoder 。
5.2、wire.Build 生成函数
我们在 wire.go (文件名非强制,但一般约定如此)文件中定义 injector 函数签名。然后在函数体中调用wire.Build ,并以所需 provider 作为参数(无须考虑顺序,就是与参数顺序无关)。
5.3、wire.go中的函数返回值,编译
由于wire.go中的函数并没有真正返回值,为避免编译器报错, 简单地用panic函数包装起来即可。不用担心执行时报错, 因为它不会实际运行,只是用来生成真正的代码的依据。
5.4、build*** wireinject 标签含义
wire.go 第一行 // *+build* wireinject ,这个 build tag 确保在常规编译时忽略 wire.go 文件(因为常规编译时不会指定 wireinject 标签)。
5.5、build*** !wireinject 标签含义
与之相对的是 wire_gen.go 中的 //*+build* !wireinject 。两组对立的 build tag 保证在任意情况下, wire.go 与 wire_gen.go 只有一个文件生效, 避免了“UserLoader 方法被重复定义”的编译错误.
5.6、简单的初始化过程 ,error 处理
自动生成的 UserLoader 代码包含了 error 处理。与我们手写代码几乎相同。对于这样一个简单的初始化过程, 手写也不算麻烦。但当组件数达到几十、上百甚至更多时, 自动生成的优势就体现出来了。
5.7、go generate 或 wire 生成
要触发“生成”动作有两种方式:go generate 或 wire 。前者仅在 wire_gen.go 已存在的情况下有效(因为 wire_gen.go 的第三行 //*go:generate* wire),而后者在任何时候都有可以调用。并且后者有更多参数可以对生成动作进行微调, 所以建议始终使用 wire 命令。
网友评论