golang wire 依赖注入

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 命令。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • go wire 前提:已经将$GOPATH/bin目录添加到环境变量$PATH安装go get github.co...
    戈壁堂阅读 7,336评论 0 0
  • Awesome GitHub Topic for Go Awesome Go golang-open-source...
    Liam_ml阅读 9,304评论 2 14
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,323评论 19 139
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 12,720评论 28 53
  • 首先介绍下自己的背景: 我11年左右入市到现在,也差不多有4年时间,看过一些关于股票投资的书籍,对于巴菲特等股神的...
    瞎投资阅读 11,044评论 3 8