Implicit interface conversion to golang

Here is an example of an idea that I want to demonstrate.

package main
import "fmt"

// interface declaration
//

type A interface {
    AAA() string
}

type B interface{
    Get() A
}

// implementation
//

type CA struct {}

// implementation of A.AAA
func (ca *CA) AAA() string {
    return "it CA"
}

type C struct {}

// implementation of B.Get, except for returning a 'struct' instead of an 'interface'
func (c *C) Get() *CA {
    return &CA{}
}

func main() {
    var c interface{} = &C{}
    d := c.(B)
    fmt.Println(d.Get().AAA())
    fmt.Println("Hello, playground")
}

      

In this example

  • B

    has a method Get

    to return an interfaceA

  • struct C

    has a member function Get

    to return a pointer to a struct CA

    that implements the interfaceA

As a result, Go cannot infer an interface B

from a struct C

, even their method Get

differs only from the return type, which is convertible.

The reason I am raising this question is when interface A, B and struct C, CA are in different packages, I can only:

  • refine the Get method from C

    to func Get () A , which introduces some dependency between packages.
  • refine the Get

    interface method B

    and struct C

    to func Get () interface {}

I want to avoid dependency between packages and try not to rely on the {} interface , can anyone give me some hint? What's the best practice in Go?

+3


source to share


1 answer


Your current type *C

does not implement an interface B

, so you cannot assign a value to *C

a type variable, B

and you cannot "type assert" a value B

from something containing a value of the type *C

.

Here's what you can do. Since you are already using the struct ( &C{}

) literal , you can declare a c

type *C

you can call it a method Get()

, and you can convert the return value C.Get()

to A

(because the return value implements A

):

var c *C = &C{}
var a A = c.Get() // This is ok, implicit interface value creation (of type A)
fmt.Println(a.AAA())
// Or without the intermediate "a", you can simply call:
fmt.Println(c.Get().AAA())

      

Output:



it CA
it CA

      

Or refactoring:

The problem is that you have an interface ( B

) that you want to implement, which has a method that returns another interface ( A

). To implement this interface B

, you must have a dependency on the package that defines A

, you cannot avoid it. And you must declare C.Get()

to return A

(instead of a specific struct type).

You can move A

to a third package, and the package that defines c

will only have to depend on that third package, but will not depend on the package that defines B

(but will still implicitly implement the interface type B

).

+3


source







All Articles