
Wire 报 returns cleanup but injection does not return cleanup function 怎么排查 injector 签名【免费下载链接】wireCompile-time Dependency Injection for Go项目地址: https://gitcode.com/GitHub_Trending/wi/wire当你在 Go 项目中用 Wire 做编译期依赖注入在包含 injector 的包目录下执行wire生成代码时可能收到这样的错误example.com/foo/wire.go:x:y: inject injectFoo: provider for example.com/foo.Foo returns cleanup but injection does not return cleanup function以上为仓库测试数据中的期望输出行号x:y是测试占位实际运行时会显示真实位置。这条错误的含义是provider set 里有一个 provider 返回了 cleanup 函数但 injector 函数的返回值中没有对应的 cleanup 函数。本文基于 Wire 仓库的用户指南docs/guide.md和internal/wire/testdata下的官方测试用例给出从报错定位到修复、再验证生成的完整排查路径。报错信息怎么读错误信息本身已经给出了定位线索。对照仓库测试用例 InjectorMissingCleanup 的期望输出格式为文件位置: inject injector名: provider for 包名.类型名 returns cleanup but injection does not return cleanup functioninject injectFoo出问题的 injector 函数名provider for example.com/foo.Foo提供类型Foo的那个 provider——问题就出在它返回了 cleanup 函数后半句说明根因injector 的签名没有声明对应的 cleanup 返回值。所以排查的第一步不是通读全部 provider而是根据报错里的类型名找到具体那个 provider确认它的返回值。核对 provider 的返回值在测试用例 internal/wire/testdata/InjectorMissingCleanup/foo 中provider 定义在 foo.gofunc provideFoo() (Foo, func()) { return Foo(42), func() {} }第二个返回值func()就是 cleanup 函数。用户指南docs/guide.md 的 Cleanup functions 一节规定cleanup 函数必须具有func()签名并且保证在任何该 provider 的输入 provider 的 cleanup 函数之前被调用。而同一目录的 injector 声明wire.go却是func injectFoo() Foo { // provideFoo returns a cleanup, but injectFoo does not. wire.Build(provideFoo) return Foo(0) }injector 只返回Foo没有 cleanup 返回值——这正是报错的原因。判定规则来自根目录 wire.go 中Build的文档注释the first return value is the output of the injector function, the optional second return value is a cleanup function, and the optional last return value is an error. If any of the provider functions in the injector functions provider set return errors or cleanup functions, the corresponding return value must be present in the injector function template.也就是说provider set 中只要有 provider 返回 cleanup 或 errorinjector 模板的返回值里就必须有对应的 cleanup第二个返回值和/或error最后一个返回值。修改 injector 签名修复方式是把 cleanup 函数加进 injector 的返回值。对上面的例子改法如下func injectFoo() (Foo, func()) { wire.Build(provideFoo) return Foo(0), nil }如果 provider 同时返回 error即provideXxx() (T, func(), error)形式injector 必须同时声明 cleanup 和 error且顺序固定为func()在error之前。仓库测试用例 PartialCleanup 展示了这种签名func injectBaz() (Baz, func(), error) { wire.Build(provideFoo, provideBar, provideBaz) return 0, nil, nil }只涉及 cleanup、不涉及 error 时参考测试用例 Cleanup 的 injector 签名func injectBar() (*Bar, func()) { wire.Build(provideFoo, provideBar) return nil, nil }注意 injector 模板体里的return只起占位作用返回值的类型必须正确值会被生成代码忽略所以从return Foo(0)改成return Foo(0), nil即可。另外承载 injector 的文件要带wireinject构建标签如//build wireinject避免 stub 参与最终构建这一点上述测试用例文件头部均有体现。重新生成并验证修复签名后在 injector 所在的包目录下重新运行wire成功条件有两个wire不再输出returns cleanup but injection does not return cleanup function错误生成的wire_gen.go中出现了聚合的 cleanup 函数。以 Cleanup/want/wire_gen.go 的期望输出为例文档示例生成结果类似func injectBar() (*Bar, func()) { foo, cleanup : provideFoo() bar, cleanup2 : provideBar(foo) return bar, func() { cleanup2() cleanup() } }可以看到两个要点cleanup 被聚合成一个func()返回给调用方调用顺序是后创建的 provider 先清理cleanup2()先于cleanup()。如果某个 provider 在注入过程中返回 error生成代码会在错误路径上调用已收集到的 cleanup 并返回 error——PartialCleanup/want/wire_gen.go 展示了这种带 error 分支的生成形式可作为你验证自己生成结果的对照。wire_gen.go生成之后后续可以用go generate重新生成wire_gen.go头部带有//go:generate指令见上方生成示例。相关限制cleanup 函数必须是func()类型不能带参数或返回值docs/guide.md、wire.go。错误信息与 cleanup 规则是对称的provider 返回 error 而 injector 没有返回error时Build文档注释中的同一判定规则同样适用修复方式在 injector 返回值末尾加上error与本文一致。injector 返回的聚合 cleanup 由调用方负责调用例如 Cleanup/foo/foo.go 的main中在用完bar后显式调用cleanup()。如果你的 provider set 较复杂报错只会指出触发该条错误的那个 provider按读报错 → 核对 provider 返回值 → 补全 injector 返回值 → 重新运行wire的顺序处理直到wire无错误输出且wire_gen.go按上述形式生成。【免费下载链接】wireCompile-time Dependency Injection for Go项目地址: https://gitcode.com/GitHub_Trending/wi/wire创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考