I have been working with Go on and off on my free time for a few months and I feel I've been getting a hang of it. Coming from traditional OOP languages, such as Java and PHP, I had a hard time grasping composition and embedding in Go. I think it finally clicked recently and want to use it more, but I have hit a roadblock for one idea I have.
Lets say I have a struct from a package that has a Validate method and I embedded that in my struct in the package I am currently working in. Is there a way (I own both packages) that I can get a reference to the struct that is doing the embedding inside of the Validate method? Kind of like a way to see who called me since I would be calling it on the "parent" instead of the embedded.
I'll try to visualize this...
type B struct {}
func (b B) Validate() {
// get reference somehow of A obj
}
type A struct {
B
}
a := A{B{}}
a.Validate()
I feel as though this isn't possible, but it would be cool if you could. I'd imagine that you would need to make A and B both the same interface type for this to work. Any thoughts or help will be much appreciated.
This is something not possible. To better understand why, see this slightly modified version of your example:
Output as expected, the same value of
*B
everywhere (Go Playground):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 ofB
) to embed in different values of typeA
!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 ofA
, you can call the promoted methodB.Validate()
by writinga.Validate()
which is OK, but you can also call it likea.B.Validate()
- now this time you don't really have a value ofA
(arguable, butValidate()
is called on a value of*B
and notA
), but finally you can also callb.Validate()
- this time you definitely don't have a value ofA
.There is no definite type for the parent,
B
(or*B
) can be embedded in any type (so it couldn't be anything other thaninterface{}
).So image: you have a concrete value of
*B
and when itsValidate()
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 theValidate()
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 callB.Validate()
like this:There is no justification for a validator of the kind you imagine to be embedded in
A
, it should just be a field ofA
, or since there is no direct relation, it can be an "independent" validator. In both of these cases you may add a helperValidate()
method toA
if you would like to simplify validation.Any kind of
parent
reference is impossible. What would you hope to do with the parent? Since they would be potentially widely different types, they would be incompatible to do anything meaningful with.If you need something in common between different types you want an interface, and you will need to pass it in:
If you can explain what you are actually trying to accomplish there is almost certainly a better way than this.