Home > Software design >  I want to create interface for dig
I want to create interface for dig

Time:11-01

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

  •  Tags:  
  • go
  • Related