我想为dig创建一个界面。

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

I want to create interface for dig

问题

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

type Container interface {
    Provide(constructor interface{}, opts ...interface{}) error
    Invoke(function interface{}, opts ...interface{}) error
}

但是出现了一个错误:

#13 0.387 cmd/app/main.go:26:40: cannot use container (type *dig.Container) as type application.Container in argument to application.NewApplication:
#13 0.387       *dig.Container does not implement application.Container (wrong type for Invoke method)
#13 0.387               have Invoke(interface {}, ...dig.InvokeOption) error
#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:

type Container interface {
    Provide(constructor interface{}, opts ...interface{}) error
    Invoke(function interface{}, opts ...interface{}) error
}

but an error occurs:

#13 0.387 cmd/app/main.go:26:40: cannot use container (type *dig.Container) as type application.Container in argument to application.NewApplication:
#13 0.387       *dig.Container does not implement application.Container (wrong type for Invoke method)
#13 0.387               have Invoke(interface {}, ...dig.InvokeOption) error
#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列表。

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

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

package main

import (
	"fmt"
)

type T struct{}

func main() {
    var Ts = []T{
	T{}, T{}, T{},
    }
    fmt.Println(Ts...)    
}

它将无法编译,即使每个单独的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

英文:
Cannot use container (type *dig.Container) as type application.Container in argument to application.NewApplication:
       *dig.Container does not implement application.Container (wrong type for Invoke method)
               have Invoke(interface {}, ...dig.InvokeOption) error
               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:

package main

import (
	"fmt"
)

type T struct{}

func main() {
    var Ts = []T{
	T{}, T{}, T{},
    }
    fmt.Println(Ts...)    
}

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:

确定