Can embedded struct method have knowledge of parent/child?

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.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)