对于下面的代码,我希望得到的输出是 {"NewName" [{"NewName" []}]}
但它没有更新子结构。我们如何确保它更新层次结构中的每个结构。
package main
import (
"fmt"
)
type red struct {
Name string
Child []red
}
func (r *red) setName(nameString string){
r.Name = nameString
for _, child := range r.Child{
child.setName(nameString)
}
}
func main() {
obj := red{Name:"NameA",Child:[]red{red{Name: "NameB"}}}
fmt.Print(obj)
fmt.Print("\n")
obj.setName("NewName")
//Expectation {"NewName" [{"NewName" []}]}
fmt.Print(obj)
}
你不需要像其他答案所建议的那样到处使用指针。你的代码中的问题是,当你迭代childs时,你得到了每个copy的值,在这个copy上设置了名字,但没有把这个copy保存到slice中。
package main
import (
"fmt"
)
type red struct {
Name string
Child []red
}
func (r *red) setName(s string) {
r.Name = s
for i, ch := range r.Child {
ch.setName(s) // ch is not a ptr to r.Child[i], it is a value copy
r.Child[i] = ch // so you must re assign the copy into the slice!
}
}
func main() {
obj := red{Name: "A", Child: []red{red{Name: "B"}}}
fmt.Print(obj)
fmt.Print("\n")
obj.setName("X")
//Expectation {X [{X []}]}
fmt.Print(obj)
}
其实问题出在这里
for _, ch := range r.Child{
ch.setName(s)
}
你正在更新使用 ch
这是不更新的你 r.Child
实际上是切片。你的代码相当于这样
var ch red
for i, _:= range r.Child{
ch = r.Child[i]
ch.setName(s)
}
为了解决这个问题,你可以这样更新片子。
for i, _ := range r.Child {
r.Child[i].setName(s) // access the slice eliment by index and update
}
而这是一个很好的模式,可以使用 []*red
为孩子。
你应该让 Child
做 []*red
而不是 []red
以防止红色的副本被创建。
请看下面的调整(the String
方法只是为了让输出看起来更漂亮,否则我们会得到内存地址打印)。)
package main
import (
"fmt"
)
type red struct {
Name string
Child []*red
}
func (r *red) String() string {
ret := fmt.Sprintf("{%s [", r.Name)
for _, c := range r.Child {
ret = ret + c.Name + " "
}
ret += "]}"
return ret
}
func (r *red) setName(s string) {
r.Name = s
for _, ch := range r.Child {
ch.setName(s)
}
}
func main() {
obj := red{Name: "A", Child: []*red{&red{Name: "B"}}}
fmt.Print(obj)
fmt.Print("\n")
obj.setName("X")
//Expectation {X [{X []}]}
fmt.Print(obj)
}
你可以通过改变 Child []red
到一个指针列表。Child []*red
.
下面是完整的代码 去游乐场
package main
import (
"fmt"
)
type red struct {
Name string
Child []*red
}
func (r *red) setName(s string){
r.Name = s
for _, ch := range r.Child{
ch.setName(s)
}
}
func main() {
obj := red{Name:"A",Child:[]*red{&red{Name: "B"}}}
fmt.Println(obj.Name)
for _, ch := range obj.Child{
fmt.Println(ch.Name)
}
fmt.Print("\n")
obj.setName("X")
//Expectation X \n X
fmt.Println(obj.Name)
for _, ch := range obj.Child{
fmt.Println(ch.Name)
}
}