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?
CodePudding user response:
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.InvokeOption
s, which individually satisfy interface{}
. You'll still have to convert the interface{}
s back to *dig.InvokeOption
s within dig.Container.Invoke
.