Reputation: 365
I've been working in an interface to use as a hierarchical tree. The idea is to aloud the concrete implementations to call .Children()
, .Father()
and a function to auto populate the hierarchy based on a slice of {id, FatherId}
schema.
I only need three different implementations of this interface, maybe it's more convenient to do the whole thing for each struct but I'm new to Go and decided to use this example to understand interfaces.
I've come to an interface that looks something like this:
type Node interface{
Equals(nodo *Node) bool
AddChild(child *Node)
SetFather(father *Node)
Children() []Node
Father() *Node
}
So the idea is call a Populate
function:
func Populate(plainNodes []Node, HierarchichalNodes *[]Node) {}
Plain nodes would be items defining the id of his father:
{id: "Animal", father: ""}
{id: "Plant", father: ""}
{id: "Mammals", father: "Animal"}
Hierarchical nodes would be the result:
Animal
|__Mammals
Plant
The problem I'm getting is when I try to implement the interface in a concrete struct, this case "Category"
.
type Category struct{
children []Category
father Category
}
func (c Category) SetFather(node *Node) {
v, ok = node.(*Category)
c.father = v
}
Notice that in Category
I want to work with Category
father and children, not with interface Node
.
I can't do the conversion, I get :
invalid type assertion: nodo.(*Category) (non-interface type *Node on left)
Any ideas?
Upvotes: 8
Views: 19153
Reputation: 1459
This should work:
(*nodo).(Category)
De-reference first, assert afterwards.
Upvotes: 4
Reputation: 417452
Your parameter is node *Node
, it is of type *Node
. Node
is an interface type, but *Node
is not: it is a pointer to interface.
Don't use pointer to interface, it is very rarely needed. Instead change it to node Node
. Also change all your other *Node
pointers to just Node
.
Also if Category.SetFather()
method intends to change the Category
value identified as the receiver, it must be a pointer else you'd only end up changing a copy which will be discarded after SetFather()
returns. So use a receiver like c *Category
.
Going further, if the node
argument contains a *Category
wrapped in an interface, you can't directly assign it to Category.father
as that is a non-pointer type Category
. You need a pointer indirection, e.g. c.father = *v
; or change the type of the father
field to be a pointer: father *Category
.
Corrected SetFather()
method could look like this:
func (c *Category) SetFather(node Node) {
if v, ok := node.(*Category); ok {
c.father = *v
}
}
Upvotes: 8