I expect the following recursive code to return all base elements (= elements that do not have children). However, I seem to only retrieve the elements of the last recursive iteration. When printing the elements that are appended to the slice I see that all members I expect are actually added. That means my baseElements slice "forgets" its content. I assume it has to do with the declaration of baseElements at the beginning but I don't know how to get rid of it.
func (d *Dimension) GetBaseElements(element *Element) []*Element {
var baseElements []*Element
if d.Name != element.Dimension.Name {
return nil
}
for _, elem := range d.Elements {
for _, parent := range elem.Parents {
if parent.Parent.Name == element.Name {
if parent.Element.IsBaseElement() == true {
baseElements = append(baseElements, parent.Element)
} else {
return d.GetBaseElements(parent.Element)
}
}
}
}
return baseElements
}
Does anybody have an idea? Also any general code style etc. feedback is very welcome. I'm actually a finance person so don't be too harsh please:-).
Edit: Solved. See comments.
评论:
The_Sly_Marbo:
mentally_lazy:I think the issue is that your call to
return d.GetBaseElements(parent.Element)
could returnnil
in the third line of the function. You probably want to doreturn append(baseElements, d.getBaseElements(parent.Element))
instead.As for style, it's generally fine but the
== true
part is redundant, and it would be slightly more idiomatic to call the methodBaseElements
thanGetBaseElements
. See Effective Go on this.This is much more personal style, but I would tend to use the "return early" pattern too, replacing the loop with:
for _, elem := range d.Elements { for _, parent := range elem.Parents { if parent.Parent.Name != element.Name { continue } if !parent.Element.IsBaseElement() { return append(baseElements, d.GetBaseElements(parent.Element)) } baseElements = append(baseElements, parent.Element) } }
This results in code that's less indented, so it's a little easier to follow (in my opinion).
The_Sly_Marbo:Thanks for the great advice! The code really looks much more transparent this way. Always when looking at code people write it seems to me their functions only consist of a return statement. My ones have x loops and if conditions. Using those unnecessary "Else" parts helps a lot as it seems.
The issue with the return statement ... return append(baseElements, d.GetBaseElements(parent.Element)) ... is that the function GetBaseElements returns a slice but the append can only handle a normal Element struct. Any idea how to get around that?
mentally_lazy:Ah, I had forgotten about that. Expand the slice with the
...
operator:return append(baseElements, d.GetBaseElements(parent.Element)...)
Ah. Fantastic. Thank you so much!!! It works finally!!
