Simple recursion - Losing values

polaris · 2017-02-28 03:00:11 · 517 次点击    
这是一个分享于 2017-02-28 03:00:11 的资源,其中的信息可能已经有所发展或是发生改变。

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:

I think the issue is that your call to return d.GetBaseElements(parent.Element) could return nil in the third line of the function. You probably want to do return 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 method BaseElements than GetBaseElements. 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).

mentally_lazy:

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?

The_Sly_Marbo:

Ah, I had forgotten about that. Expand the slice with the ... operator:

return append(baseElements, d.GetBaseElements(parent.Element)...)
mentally_lazy:

Ah. Fantastic. Thank you so much!!! It works finally!!


入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

517 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传