我想为dig创建一个界面。

huangapple go评论107阅读模式
英文:

I want to create interface for dig

问题

我是一个Go语言的新手。
我想要抽象出服务容器的实现:

  1. type Container interface {
  2. Provide(constructor interface{}, opts ...interface{}) error
  3. Invoke(function interface{}, opts ...interface{}) error
  4. }

但是出现了一个错误:

  1. #13 0.387 cmd/app/main.go:26:40: cannot use container (type *dig.Container) as type application.Container in argument to application.NewApplication:
  2. #13 0.387 *dig.Container does not implement application.Container (wrong type for Invoke method)
  3. #13 0.387 have Invoke(interface {}, ...dig.InvokeOption) error
  4. #13 0.387 want Invoke(interface {}, ...interface {}) error

我做错了什么?
我应该如何正确声明接口?

英文:

I'm a novice in golang.
I want to abstract from the implementation of the service container:

  1. type Container interface {
  2. Provide(constructor interface{}, opts ...interface{}) error
  3. Invoke(function interface{}, opts ...interface{}) error
  4. }

but an error occurs:

  1. #13 0.387 cmd/app/main.go:26:40: cannot use container (type *dig.Container) as type application.Container in argument to application.NewApplication:
  2. #13 0.387 *dig.Container does not implement application.Container (wrong type for Invoke method)
  3. #13 0.387 have Invoke(interface {}, ...dig.InvokeOption) error
  4. #13 0.387 want Invoke(interface {}, ...interface {}) error

What am I doing wrong?
How I can declare interface correct?

答案1

得分: 2

这意味着*dig.Container不能满足application.Container接口的要求。它进一步解释了application.Container要求Invoke方法接受一个可变参数的interface{}列表,但*dig.Container接受一个可变参数的dig.InvokeOption列表。

尽管空接口可以存储任何类型,但这并不意味着任何切片类型自动成为空接口切片(这是泛型的一个重要动机,很快就会推出)。

我记得我自己也曾对此感到困惑。考虑以下代码:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. type T struct{}
  6. func main() {
  7. var Ts = []T{
  8. T{}, T{}, T{},
  9. }
  10. fmt.Println(Ts...)
  11. }

它将无法编译,即使每个单独的T都满足interface{},因为[]T不是[]interface{}

./prog.go:13:16: cannot use Ts (type []T) as type []interface {} in argument to fmt.Println

最简单的解决方案是使dig.ContainerInvoke函数与application.ContainerInvoke签名匹配。您仍然可以将*dig.InvokeOption列表传递给它,这些列表分别满足interface{}。您仍然需要在dig.Container.Invoke内将interface{}转换回*dig.InvokeOption

英文:
  1. Cannot use container (type *dig.Container) as type application.Container in argument to application.NewApplication:
  2. *dig.Container does not implement application.Container (wrong type for Invoke method)
  3. have Invoke(interface {}, ...dig.InvokeOption) error
  4. want Invoke(interface {}, ...interface {}) error

This means *dig.Container doesn't satisfy the interface application.Container. It goes on to explain that application.Container requires the Invoke method to take a variadic list of interface{}, but *dig.Container takes a variadic list of dig.InvokeOption.

Even though an empty interface can store any type, that does not mean that any slice type is automatically also a slice of empty interfaces (That's a big motivation for Generics, which should come out soon).

I remember being confused by this myself. Consder this code:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. type T struct{}
  6. func main() {
  7. var Ts = []T{
  8. T{}, T{}, T{},
  9. }
  10. fmt.Println(Ts...)
  11. }

It will not compile, even thought each individual T satisfies interface{} because a []T is not an []interface{}:

> ./prog.go:13:16: cannot use Ts (type []T) as type []interface {} in argument to fmt.Println

The easiest solution here would be to make dig.Container's Invoke function match the Invoke signature of application.Container. You can still pass it a list of *dig.InvokeOptions, which individually satisfy interface{}. You'll still have to convert the interface{}s back to *dig.InvokeOptions within dig.Container.Invoke.

huangapple
  • 本文由 发表于 2021年11月1日 02:03:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/69789244.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定