2
votes

I have this example

// embed project main.go
package main

import (
    "fmt"
)

type A struct {
    A1 int
    A2 int
}

func (a A) Incr() int {
    a.A1++
    return a.A1
}

type B struct {
    A
    D int
}

type C interface {
    Incr() int
}

func Add(c C) {
    d := c.Incr()
    fmt.Println(d)
}

func main() {
    var s B
    s.Incr() //B has Incr
    Add(s)
}

Using this example i wanted to check whether B implement interface C or not. In this example Add accept s (type B) as input. B implement C.

But when i change Incr() method from original to

func (a *A) Incr() int {
    a.A1++
    return a.A1
}

It compiler gives the error

./main.go:35: cannot use s (type B) as type C in argument to AddContent: B does not implement C (Incr method has pointer receiver)

So i am still confused whether a struct implement all the interface that one of their embedded type implement.

2

2 Answers

2
votes

If S contains an anonymous field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.

If S contains an anonymous field *T, the method sets of S and *S both include promoted methods with receiver T or *T.

B embedded A, so method sets of B include protomoted methods with receiver A, but does not include *A

2
votes

Yes, your struct implements the method set of the embedded type.

However, when you change the signature of Incr to func (a *A) Incr() int, you need a pointer for the receiver of that method. A itself doesn't implement Incr when it has a pointer receiver.

The reason the s.Incr() call works, is that the s value is addressable, and Go automatically references it for the method call. When you pass s to Add, you're attempting to convert it to a C interface, the value would no longer be addressable, and the Incr method isn't in the method set.

In this case, you can either change the embedded type to *A,

type B struct {
    *A
    D int
}

take the address of s at the call site

Add(&s)

or make s a pointer (*B):

s := &B{}
Add(s)

The relevent portion of the spec

Given a struct type S and a type named T, promoted methods are included in the method set of the struct as follows:

  • If S contains an anonymous field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
  • If S contains an anonymous field *T, the method sets of S and *S both include promoted methods with receiver T or *T.