go 依賴注入工具( go-wire )使用(一 講解)

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
}
``
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章