The following example is basic node hierarchy implementation which I would like to embed into other structs:
package main
import "fmt"
type NodeInterface interface {
AddChild(child NodeInterface)
RemoveChild(child NodeInterface)
RemoveFromParent()
setParent(parent NodeInterface)
}
type Node struct {
parent NodeInterface
children []NodeInterface
}
func (n *Node) setParent(parent NodeInterface) {
n.parent = parent
}
func (n *Node) AddChild(child NodeInterface) {
n.children = append(n.children, child)
child.setParent(n)
}
func (n *Node) RemoveChild(child NodeInterface) {
found := false
var index int
for i, node := range n.children {
if node == child {
found = true
index = i
break
}
}
if found {
n.children = append(n.children[:index], n.children[index+1:]...)
} else {
panic(fmt.Sprintf("child not found; given: %T; existing: %T", child, n.children[0]))
}
}
func (n *Node) RemoveFromParent() {
n.parent.RemoveChild(n)
}
func main() {
apex := &Node{}
cl := &Node{}
apex.AddChild(cl)
cl.RemoveFromParent()
}
So, when I try this:
type Foo struct {
Node
}
func main() {
apex := &Foo{}
cl := &Foo{}
apex.AddChild(cl)
cl.RemoveFromParent()
}
it panics:
child not found; given: *main.Node; existing: *main.Foo
— which is kind-of understandable.
But how to get it to work? I do want to bring the ability to form hierarchies to arbitrary structs like Foo
.
The problem lies in the difference of the entities being compared in this line:
if node == child {
One is Node
, the other is whatever type embeds Node
(Foo
in this case).
So, if we make both Node
, that will be it. But how?
Implement getNode()
:
func (n *Node) getNode() NodeInterface {
return n
}
and then compare Nodes:
if node.getNode() == child.getNode() {