Why can't I use an interface which needs another interface inside of it

141 views
Skip to first unread message

Rodrigo Araujo

unread,
Mar 13, 2024, 10:02:50 AMMar 13
to golang-nuts
Given the code bellow, I'm trying to keep my packages completely separated, without knowing each other, but the code doesn't work. I just can get it running when I define (or use) an interface from one package inside code of the other package.
Here is the error:
cannot use client (variable of type *a.Client) as b.GetChilder value in struct literal: *a.Client does not implement b.GetChilder (wrong type for method GetChild)
have GetChild() *a.Child
want GetChild() b.GetDataer
compilerInvalidIfaceAssign


package a // file: a/a.go

import "fmt"

type Client struct{}

func (c *Client) GetChild() *Child {
    return &Child{}
}

type Child struct{}

func (c *Child) GetData() {
    fmt.Println("from GetData")
}


package b // file: b/b.go

type GetDataer interface {
    GetData()
}

type GetChilder interface {
    GetChild() GetDataer
}

type Processor struct {
    Client GetChilder
}

func (p *Processor) Process() {
    card := p.Client.GetChild()
    card.GetData()
}


package main // file: main.go

import (
    "interfaces/a"
    "interfaces/b"
)

func main() {
    client := &a.Client{}
    processor := &b.Processor{
        Client: client,
    }
    processor.Process()
}


Why this doens't work? Some kind of limitation on interfaces usage?
How is the best approach (idiomatic golang) to tacke this kind of problem?


Brian Hatfield

unread,
Mar 13, 2024, 10:28:50 AMMar 13
to Rodrigo Araujo, golang-nuts
Client.GetChild() must return GetChilder, not Child.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/41be202c-f205-4adf-aecc-0f8e681e2490n%40googlegroups.com.

Rodrigo Araujo

unread,
Mar 13, 2024, 12:31:50 PMMar 13
to Brian Hatfield, golang-nuts
Do you mean b.GetChilder? In this case, package A will depend on package B and I don't think this is a good approach.
--
Att.
----------------------
Rodrigo Araujo
----------------------

burak serdar

unread,
Mar 13, 2024, 12:41:24 PMMar 13
to rodrigo.si...@gmail.com, Brian Hatfield, golang-nuts
On Wed, Mar 13, 2024 at 10:31 AM Rodrigo Araujo <yol...@gmail.com> wrote:
>
> Do you mean b.GetChilder? In this case, package A will depend on package B and I don't think this is a good approach.

Why would it not be a good approach? You have a package declaring
interfaces, and if you have another package using those interfaces,
you import the first package in the second. Placing common interfaces
in a package everyone else imports is a common way to deal with this
problem.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEwyvWHKZboz2KQvU7o_yneYhY31r3HBxqSQJw-B-vkuRvxHXw%40mail.gmail.com.

Rodrigo Araujo

unread,
Mar 13, 2024, 1:00:34 PMMar 13
to burak serdar, Brian Hatfield, golang-nuts
'Cause this dependency makes code more "rigid". A refactor in an isolated package would let to change other packages. Also makes testing more difficult.
It is kind of described here: https://go.dev/wiki/CodeReviewComments#interfaces

You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/E9EwsXSKg74/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAMV2Rqr6PmqU%2BHNaNwW8fOZrv6SZw7cf2pacoR_tzvd3hd0MDA%40mail.gmail.com.

Jason Phillips

unread,
Mar 13, 2024, 2:00:52 PMMar 13
to golang-nuts
Regardless, that's the reason what you've attempted doesn't work.  It has its own entry in the Go FAQ: https://go.dev/doc/faq#covariant_types

Mike Schinkel

unread,
Mar 13, 2024, 2:56:26 PMMar 13
to Brian Hatfield, Rodrigo Araujo, GoLang Nuts Mailing List
On Mar 13, 2024, at 10:27 AM, Brian Hatfield <bmhat...@gmail.com> wrote:

Client.GetChild() must return GetChilder, not Child.

Actually, Client.GetChild() must return b.GetDataer, not b.GetChilder, but the example is a mind bender  so it was easy to get wrong. I only got it correct by testing the code and failing to get it right a few times.


On Mar 13, 2024, at 12:59 PM, Rodrigo Araujo <rodrigo.si...@gmail.com> wrote:

'Cause this dependency makes code more "rigid". A refactor in an isolated package would let to change other packages. Also makes testing more difficult.
It is kind of described here: https://go.dev/wiki/CodeReviewComments#interfaces

Besides that Jason Phillips already explained the reason what you've attempted doesn't work, consider that something needs be shared.  And in Go that something is often an interface. As stated though, interfaces in Go do not work with covariance types. #fwiw

Lastly, a suggestion on naming.  My understanding is that it would be more idiomatic to name `b.GetChilder` as `b.ChildGetter()` and `b.GetDataer` as `b.DataGetter()`; that certainly reads easier, at least to me. Again, #fwiw

-Mike

Reply all
Reply to author
Forward
0 new messages