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
}
``