美文网首页
golang wire 依赖注入

golang wire 依赖注入

作者: 哆啦在这A梦在哪 | 来源:发表于2021-10-19 15:35 被阅读0次

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

    相关文章

      网友评论

          本文标题:golang wire 依赖注入

          本文链接:https://www.haomeiwen.com/subject/wupmoltx.html