Wire 有两个核心概念:providers 和 injectors。
Provider
Wire 的主要机制是 provider:能够生成值的函数。这些函数是普通的 Go 代码。
package foobarbaz
type Foo struct {
X int
}
// ProvideFoo returns a Foo.
func ProvideFoo() Foo {
return Foo{X: 42}
}
复制代码
Provider 函数必须能被导出,为了能被其他包使用,就像普通函数一样。
Provider 可以用参数指定依赖关系:
package foobarbaz
// ...
type Bar struct {
X int
}
// ProvideBar returns a Bar: a negative Foo.
func ProvideBar(foo Foo) Bar {
return Bar{X: -foo.X}
}
复制代码
Provider 也可以返回 error:
package foobarbaz
import (
"context"
"errors"
)
// ...
type Baz struct {
X int
}
// ProvideBaz returns a value if Bar is not zero.
func ProvideBaz(ctx context.Context, bar Bar) (Baz, error) {
if bar.X == 0 {
return Baz{}, errors.New("cannot provide baz when bar is zero")
}
return Baz{X: bar.X}, nil
}
复制代码
Provider 可以被分组成 provider sets
。如果要经常同时使用多个提供程序,这是很有用的。要将这些 Provider 添加到名为 SuperSet
的集合,使用 wire.NewSet
函数:
package foobarbaz
import (
// ...
"github.com/google/wire"
)
// ...
var SuperSet = wire.NewSet(ProvideFoo, ProvideBar, ProvideBaz)
复制代码
你也可以添加其他 provider set
到 provider set
中。
package foobarbaz
import (
// ...
"example.com/some/other/pkg"
)
// ...
var MegaSet = wire.NewSet(SuperSet, pkg.OtherSet)
复制代码
Injector
应用程序用 injector 将这些 providers 连接起来:injector 是一个按依赖顺序调用 providers 的函数。使用 Wire,你写 injector 的签名,然后 Wire 生成函数体。
// +build wireinject
// The build tag makes sure the stub is not built in the final build.
package main
import (
"context"
"github.com/google/wire"
"example.com/foobarbaz"
)
func initializeBaz(ctx context.Context) (foobarbaz.Baz, error) {
wire.Build(foobarbaz.MegaSet)
return foobarbaz.Baz{}, nil
}
复制代码
injector 可以像 providers 一样在输入上参数化和返回 error。wire.Build
的参数和 wire.NewSet
一样:他们来自一个 provider set
。
任何在带有 injector 的文件中发现的非注入器声明都会被复制到生成的文件中。
你可以通过在包目录中调用 Wire 来生成 injector:
Wire 会生成 injector 的实现到一个名为 wire_gen.go
文件,如下:
// Code generated by Wire. DO NOT EDIT.
//go:generate go run github.com/google/wire/cmd/wire
//+build !wireinject
package main
import (
"example.com/foobarbaz"
)
func initializeBaz(ctx context.Context) (foobarbaz.Baz, error) {
foo := foobarbaz.ProvideFoo()
bar := foobarbaz.ProvideBar(foo)
baz, err := foobarbaz.ProvideBaz(ctx, bar)
if err != nil {
return foobarbaz.Baz{}, err
}
return baz, nil
}
复制代码
正如您所看到的,输出非常接近开发人员自己编写的内容。此外,它在运行时几乎不依赖于 Wire:所有编写的代码都是普通的 Go 代码,不需要 Wire 也可以使用。
一旦创建了 wire_gen.go
, 你也可以运行 go generate
重新生成。
参考
评论