我创建了一个具有父项和子项的Element结构,创建了一个名为SubElement的辅助函数,以及一个迭代遍历所有子项以进行打印的String方法:
package main
import "fmt"
type Element struct {
parent *Element
children []Element
tag string
}
func SubElement(parent *Element, tag string) Element {
el := Element{}
el.parent = parent
el.tag = tag
parent.children = append(parent.children, el)
return el
}
func (el Element) String() string {
s := "<" + el.tag + ">"
for _, child := range el.children {
s += child.String()
}
s += "</" + el.tag + ">"
return s
}
func main() {
root := Element{}
root.tag = "root"
a := SubElement(&root, "a")
b := SubElement(&a, "b")
SubElement(&b, "c")
fmt.Println(root) // prints: <root><a></a></root>
fmt.Println(a) // prints: <a><b></b></a>
// and so on
}
我遇到的问题是,我选择打印的根节点只提供第一层子节点。我确定它与使用parent.children的附加内容相关,但缺乏对如何正确解决此问题的理解。
要解决此问题,我将children
更改为map[int]Element
。然后在我的SubElement函数中,我用parent.children[len(parent.children)] = el
“追加”。然后以正确的顺序迭代,for循环的String方法为for i:= 0; i < len(el.children); i++
,访问el.children[i]
。
但是,我想知道如何使用数组正确地执行此操作。感谢
答案 0 :(得分:4)
解释为什么[] Element版本不起作用的答案。
将结构复制为值。在SubElement
中,您创建一个Element
结构,然后当您追加它时,它实际上附加了结构的全新副本。当您返回el并将其分配给a
时,会生成另一个副本。 a
的地址不是附加的Element
的地址。
所以,你可能会变得棘手并且获取实际位于切片中的元素的地址,这甚至可能看起来像是在测试用例中工作,但是保留这些指针时会出现问题,例如当你执行时将其存储在Element.parent
中。问题是后续追加可以重新分配切片,现在你保留的指针指向一些孤立的内存而不是当前有效的切片。
如果[] * Element版本解决了其他一些问题,那么它们很可能是存储随后孤立的指针的问题。
可以使用结构切片实现树,但是需要清楚地了解将指针保留在切片中通常是一个错误。由于存储父指针不安全,因此最好将其从结构中删除。
package main
import "fmt"
func main() {
tree := Element{tag: "head"}
tree.SubElement("tier-1")
tree.children[0].SubElement("tier-2")
tree.children[0].SubElement("tier-2")
tree.SubElement("tier-1")
tree.children[1].SubElement("tier-2")
fmt.Println(tree)
}
type Element struct {
children []Element
tag string
}
func (parent *Element) SubElement(tag string) {
parent.children = append(parent.children, Element{tag: tag})
}
func (el Element) String() string {
s := "<" + el.tag + ">"
for _, child := range el.children {
s += child.String()
}
s += "</" + el.tag + ">"
return s
}
此代码至少有效;但是如果你有其他使用指针的代码,或者那些使用了父指针的代码,则必须重新考虑它。
答案 1 :(得分:2)
第一个线索是SubElement没有编译(编辑:拥有它)(最初)。你可以尝试使其工作,但我建议你将Element.children更改为{{1而不是[]*Element
。这是一个有效的例子:
[]Element
输出:
package main
import "fmt"
func main() {
tree := &Element{tag: "head"}
t1 := SubElement(tree, "tier-1")
SubElement(t1, "tier-2")
SubElement(t1, "tier-2")
t1 = SubElement(tree, "tier-1")
SubElement(t1, "tier-2")
fmt.Println(tree)
}
type Element struct {
parent *Element
children []*Element
tag string
}
func SubElement(parent *Element, tag string) *Element {
el := &Element{parent: parent, tag: tag}
parent.children = append(parent.children, el)
return el
}
func (el *Element) String() string {
s := "<" + el.tag + ">"
for _, child := range el.children {
s += child.String()
}
s += "</" + el.tag + ">"
return s
}