wire是Google开源的一款代码生成工具,通过依赖注入来自动链接不同的组件。
依赖注入 是用来构建地耦合,灵活易维护地代码的标注技术。在wire中,组件间的依赖关系表示为函数参数(function parameters),通过显示的初始化而不是全局变量。wire没有使用运行时状态或反射来实现依赖注入,而是使用代码生成。
像Wire这样的依赖注入工具旨在简化初始化代码的管理。可以将服务及其依赖关系描述为代码或配置,Wire计算出依赖关系图,并确认如何传递每个服务所需的内容。通过更改函数签名、添加或删除初始化项来更改应用程序的依赖关系,然后Wire为整个依赖关系图生成初始化代码。
Golang社区中其他的依赖注入框架,如来自Uber的dig,Facebook的inject。他们都通过反射机制实现运行时依赖注入。Wire主要灵感来自于Dagger 2,使用代码生成而不是反射或service locators。这样做带来的好处:
- 当依赖关系更加复杂时,运行时依赖注入会变得难以跟踪和调试。使用代码生成意味着在运行时执行的初始化代码是常规的,惯用的Go代码,易于理解和调试。特别是像忘记依赖之类的问题,将变成编译时错误而不是运行时错误
- 因为不需要 Service Locators, 所以对命名没有特殊要求
- 避免依赖膨胀变得更简单。Wire生成的代码仅仅只包含需要的依赖,所以构建出的程序中不会含有没有使用过的依赖。而运行时依赖注入直到执行时,才能识别出没有使用过的依赖
- 依赖关系静态存于源码之中, 便于工具分析与可视化
基本概念
Wire的两个核心概念是:providers 和 injectors。
provider
provider是Wire的核心机制,它是一个可以返回一个值的普通Go函数(function),如:
|
|
为了可以在其他包中使用,provider函数必须要可以是可以导出的,同时provider函数可以使用参数来指定依赖:
|
|
provider也可以返回error:
|
|
通过ProviderSet可以将一组provider组合到一起,实践中,通常将一些一起使用的provider放到一起组成一个ProviderSet:
|
|
provider set 可以再放入到另一个provider set 中:
|
|
Injectors
injector是由Wire工具自动生成的函数,它将按照依赖顺序调用相关的provider。
通过编写一个函数来声明一个injector,在这个函数体中,将provider作为参数调用wire.Build。wire只关注这个定义函数的返回类型,wire在生成代码时会忽略函数的返回值。
在定义injector的函数中
|
|
在包目录上执行wire命令,生成injector的代码会放到wire_gen.go文件中。如:
|
|
高级功能
接口绑定
Struct Providers
值绑定
结构的字段熟悉作为Provider
清理函数
参考资源
- https://blog.golang.org/wire
- https://github.com/google/wire
- https://github.com/google/wire/blob/main/docs/guide.md
- https://medium.com/@dche423/master-wire-cn-d57de86caa1b
- https://en.wikipedia.org/wiki/Service_locator_pattern
- https://github.com/uber-go/dig
- https://github.com/google/go-cloud
- https://github.com/google/wire/blob/main/_tutorial/README.md