go 依賴注入工具( go-wire )使用(一 講解)
共分兩篇:
go 依賴注入工具( go-wire )使用(二 用戶指南)
項目地址: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
}
``