wire 库是gogole开发的go依赖注入库。了解更多,请点击一文读懂wire
我们建议使用wire的时候遵循以下建议
区分类型
如果需要注入常见类型(字符串,整型等),请创建一个新类型,以避免与其他提供程序发生冲突。例如:
type MySQLConnectionString string
Options Structs
包含许多参数的provider函数, 考虑把参数打包成一个结构体
type Options struct {
// Messages is the set of recommended greetings.
Messages []Message
// Writer is the location to send greetings. nil goes to stdout.
Writer io.Writer
}
func NewGreeter(ctx context.Context, opts Options) (Greeter, error) {
// ...
}
var GreeterSet = wire.NewSet(wire.Struct(new(Options), "*"), NewGreeter)
功能包中的 Provider Sets
按go包中创建的 provider sets中,要保持兼容性,仅可以做如下修改:
-
删除provider 函数的参数,但是不能给函数添加新的参数,不能改变函数的返回值。
-
provider 函数添加一个全新类型的返回值,注意:必须是全新类型,如果类型不是新添加的,可能会和某个包含此类型的injector产生冲突。
如下图,T2 必须是全新的类型,否则很可能会产生冲突
除此以外的所有修改都是不安全的,包括:
-
在此provido 函数中添加新的参数
-
从 providor 函数删除一个返回值
-
添加一个已存在的输出到providor set中
⚠️:与其进行这些重大更改,不如考虑添加一个新的providor set。
例如,如果您有这样的提供程序集:
var GreeterSet = wire.NewSet(NewStdoutGreeter)
func DefaultGreeter(ctx context.Context) *Greeter {
// ...
}
func NewStdoutGreeter(ctx context.Context, msgs []Message) *Greeter {
// ...
}
func NewGreeter(ctx context.Context, w io.Writer, msgs []Message) (*Greeter, error) {
// ...
}
你可以:
-
在 Greeter 中,使用 DefaultGreeter 替代 NewStdoutGreeter
-
创建一个新类型 T, 添加 T 的 providor 到 GreeterSet 中,只要 T 是和 provider 一同新加的。
但你不能做如下操作:
-
在 GreeterSet 中 使用 NewGreeter 替换 NewStdoutGreeter。这添加了新参数(io.Writer), 并添加了一个新的error 返回
-
从 Geeter 中移除 NewStdoutGreeter, 依赖 Greeter 的注入器可能被破坏
-
添加一个 io.Writer provider 到 GeeeterSet。 注入器可能在其他地方有一个 io.Writer, 会和这个产生冲突。
所以,在provider set中,应该小心选择返回类型。通常,会偏爱小型provider set。例如:一个provider set中只包含一个 由 wire.Bind
把 返回类型和接口联系在一起的 provider 函数。避免使用较大的提供程序集可以降低应用程序遇到冲突的可能性。举例来说,假如你的go包为一个web服务,提供一个客户端。虽然将 *http.Client
的提供程序捆绑到您的库客户端的提供程序集中可能很诱人,但如果每个库都这样做,这样做会导致冲突。相反,go包的提供者集应该只包括 API 客户端的提供者,并让 *http.Client 成为提供者集的输入。
Mocking
暂不涉及, 如果有兴趣可以看一下原文
网友评论