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.
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.
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