• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
孙龙 程序员
少时总觉为人易,华年方知立业难
博客园    首页    新随笔    联系   管理    订阅  订阅
golang 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 命令。


链接:https://www.jianshu.com/p/7bef099163aa

本文来自博客园,作者:孙龙-程序员,转载请注明原文链接:https://www.cnblogs.com/sunlong88/p/16278099.html

posted on 2022-05-16 18:55  孙龙-程序员  阅读(314)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3