golang-wire依赖注入工具的使用

777 阅读2分钟

依赖注入

往往我们创建一个A对象时,需要依赖B对象,然后B对象可能又依赖于C对象,导致我们创建A对象时,需要初始化好B对象和C对象。当随着我们的项目的复杂度升级或是对象依赖关系复杂时,手动创建对象变得繁琐,这时便需要依赖注入来帮助我们管理好对象的依赖关系。

wire 工具

Go Cloud团队开发,主要有两个核心概念:Provider和Injector

Provider: 用来指定单个对象的创建

Injector: 有wire工具组织对象的依赖关系,做具体对象的创建工作

安装:

go install github.com/google/wire/cmd/wire@latest

image.png

教程

  1. 创建一个greeter.go的文件

    里面创建了Message、Greeter、Event三个结构体。 添加Provider:NewMessage、NewGreeter和NewEvent

  2. 创建一个wire.go的文件

    里面使用wire工具来指定Injector,使用了wire.Build,该函数内的参数为Provider(没有顺序要求)

  3. 在同级目录下运行命令

    wire

代码

greeter.go

type Message string

type Greeter struct {
   Grumpy  bool
   Message Message
}

type Event struct {
   Greeter Greeter
}

func NewMessage() Message {
   return Message("Hi there!")
}

func NewGreeter(m Message) Greeter {
   var grumpy bool
   if time.Now().Unix()%2 == 0 {
      grumpy = true
   }
   return Greeter{Message: m, Grumpy: grumpy}
}

func (g Greeter) Greet() Message {
   if g.Grumpy {
      return Message("go away!")
   }
   return g.Message
}

func NewEvent(g Greeter) (Event, error) {
   if g.Grumpy {
      return Event{}, errors.New("could not create event: event greeter is grumpy")
   }
   return Event{Greeter: g}, nil
}

func (e Event) Start() {
   msg := e.Greeter.Greet()
   fmt.Println(msg)
}

wire.go

// 将一组 Provider 打包
var eventSet = wire.NewSet(NewGreeter, NewMessage)

func InitializeEvent() (Event, error) {
   wire.Build(NewEvent, eventSet)
   return Event{}, nil
}

func main() {
   e, _ := InitializeEvent()
   e.Start()
}

wire_gen.go 为自动生成的代码


//go:generate go run github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

package main

import (
   "github.com/google/wire"
)

// Injectors from wire.go:

func InitializeEvent() (Event, error) {
   message := NewMessage()
   greeter := NewGreeter(message)
   event, err := NewEvent(greeter)
   if err != nil {
      return Event{}, err
   }
   return event, nil
}

// wire.go:

var eventSet = wire.NewSet(NewGreeter, NewMessage)

func main() {
   e, _ := InitializeEvent()
   e.Start()
}

解释

+build tags 用于go build 条件编译用的, 如:+build !wireinject , 表示没有 wireinject 这个tag时 编译这个文件

参考

wire/README.md at main · google/wire · GitHub

一文读懂Wire. 本文介绍了Wire的功能特点、设计理念及详细使用方法 | by Che Dan | Medium