This is something not possible. To better understand why, see this slightly modified version of your example:
type B struct{}
func (b *B) Validate() {
fmt.Printf("b:%p\n", b)
}
type A struct {
*B
}
func main() {
b := B{}
a1 := A{&b}
a2 := A{&b}
a1.Validate()
a2.Validate()
a1.B.Validate()
a2.B.Validate()
b.Validate()
}
Output as expected, the same value of *B
everywhere (Go Playground):
b: 0x1becd8
b: 0x1becd8
b: 0x1becd8
b: 0x1becd8
b: 0x1becd8
As you can see, I changed the method receiver and the embedded type to pointer of B
.
From this example it is clear: you can use the same value of B
(or rather the same address of a value of B
) to embed in different values of type A
!
And you can call Validate()
on both: so the theoretical “parent” is not even “constant” for a given value of *B
. This wouldn’t be a deal-breaker, but: having a value of A
, you can call the promoted method B.Validate()
by writing a.Validate()
which is OK, but you can also call it like a.B.Validate()
– now this time you don’t really have a value of A
(arguable, but Validate()
is called on a value of *B
and not A
), but finally you can also call b.Validate()
– this time you definitely don’t have a value of A
.
There is no definite type for the parent, B
(or *B
) can be embedded in any type (so it couldn’t be anything other than interface{}
).
So image: you have a concrete value of *B
and when its Validate()
method is called, sometimes there is a parent, and sometimes there isn’t. Then what would be the justification to have a parent at all?
Back to your example: for this Validate()
method to validate something meaningful, it should (must) be passed to the Validate()
method as a parameter – explicitly and not automatically.
The best you can do is what captncraig wrote in his answer (+1).
You can simplify it a little though if you explicitly add a method to A
which would call B.Validate()
like this:
func (a *A) Validate2() {
a.Validate(a)
}
// And using it:
a.Validate2()
There is no justification for a validator of the kind you imagine to be embedded in A
, it should just be a field of A
, or since there is no direct relation, it can be an “independent” validator. In both of these cases you may add a helper Validate()
method to A
if you would like to simplify validation.