一.假设需要定义多个有依赖的启动项(代码如下)
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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
2020-05-16 golang复制一个指针对象(反射)