英文:
Idiomatic golang: accessing and updating an item in a struct
问题
所以我正在尝试编写一些代码,使我能够编辑结构体中数组中的值。这个示例使用"Status"作为可能要更改的值,但这只是为了简化以便更好地表达我的意图。
package main
import (
"fmt"
)
type Parent struct {
Children []Child
}
type Child struct {
Status string
}
func (p *Parent) Add() *Child {
var child Child
child.Status = "1"
p.Children = append(p.Children, child)
return &p.Children[len(p.Children)-1]
}
func main() {
var p Parent
child := p.Add()
child.Status = "2"
fmt.Println(p)
fmt.Println(child)
}
这种方式感觉不太"正规"。在golang中应该如何处理这种情况?当然,我可以将值作为参数传递进去,但在我的特定情况下,我想在添加子项后编辑Child结构体内部的函数指针(为了保持代码简洁,此处未包含)。这样做感觉更好,但也许我只需要将它们作为参数传递给Add方法?
例如:
func (p *Parent) Add(fn1 func(), fn2 func()) *Child {
// 在这里处理函数指针
}
无论如何,我只是想知道是否有人对这种情况有什么想法。
英文:
So I am trying to write some code that allows me to edit values in an array in a struct. This example uses "Status" as a possible value to alter, but this is just a simplification to try to get my intent across.
package main
import(
"fmt"
)
type Parent struct {
Children []Child
}
type Child struct {
Status string
}
func (p *Parent) Add() *Child {
var child Child
child.Status = "1"
p.Children = append(p.Children, child)
return &p.Children[len(p.Children)-1]
}
func main() {
var p Parent
child := p.Add()
child.Status = "2"
fmt.Println(p)
fmt.Println(child)
}
This doesn't feel "proper". How should I do this in golang? Certainly I could pass the value in as a parameter, but in my particular case I would like to edit function pointers that are inside the Child struct (not in this code to keep it short) after having added the child. That feels nicer, but maybe I just need to pass them as parameters to the Add method?
eg
func (p *Parent) Add(fn1 func(), fn2 func()) *Child {
Anyway just wondering if anybody has any thoughts on this type of situation.
答案1
得分: 2
我认为你应该在Add方法之外创建Child
并将其传递进去。如果你想要操作Child
,请在传递之前进行操作。你可以使用Child
结构体上的方法来实现:
func (c *Child) Init(fn1 func(), fn2 func()) {
c.Status = "1"
...
}
func (p *Parent) Add(c *Child) *Child {
p.Children = append(p.Children, c)
return c
}
func main() {
var p Parent
var child Child
child.Init(...) // <- 在这里传递一些内容...
p.Add(&child)
child.Status = "2"
fmt.Println(p)
fmt.Println(child)
}
英文:
I think you should create the Child
outside of the Add method and pass it in. If you want to manipulate the Child, do that before you passed it in. You might use methods on the Child
struct to do that:
func (c *Child) Init(fn1 func(), fn2 func()) {
c.Status = "1"
...
}
func (p *Parent) Add(c *Child) *Child {
p.Children = append(p.Children, c)
return c
}
func main() {
var p Parent
var child Child
child.Init(...) // <- pass something in there...
p.Add(&child)
child.Status = "2"
fmt.Println(p)
fmt.Println(child)
}
答案2
得分: 1
我建议以最简单的方式完成这个任务。记住KISS原则,即“保持简单”。系统的每个部分只做一件事。
按照这个逻辑,你的Add(c *Child)
方法应该只负责添加一个子元素。创建Child
应该单独完成,同样,给Child
设置一些独特的属性也应该单独完成。
对于你的OpenGL菜单系统,这种方法也很适用:
m := NewMenu()
t := NewText(text)
t.OnClick = someCallback
// 其他t的初始化操作。
m.Add(t)
// 如果t是一个指针并且m.Add没有进行复制,那么稍后你仍然可以更改t。
t.OnHover = someOtherCallback
关于是否将标签公开,或者隐藏它们并提供getter和setter方法,这取决于你的系统设计和一致性要求,由你自己决定。
英文:
I'd suggest doing this in the simplest way possible. Remember the KISS principle. One part of the system does one and only one thing.
Following this logic, your Add(c *Child)
method should only add a child. Creating a Child
should be done separately, same for giving a Child
some unique properties.
For your OpenGL menu system, this approach fits nicely as well:
m := NewMenu()
t := NewText(text)
t.OnClick = someCallback
// Some other t initialisation.
m.Add(t)
// Some time later you can still change t if it's a pointer and m.Add
// doesn't copy.
t.OnHover = someOtherCallback
The decision on whether to keep your labels exported, or hide them and provide getters/setters is up to you, and depends solely on your system's design and consistency requirements.
答案3
得分: 1
好的,以下是翻译好的代码:
package main
import (
"fmt"
)
type HairColor func() string
type Parent struct {
Children []*Child
}
type Child struct {
Age int
ShowHairColor HairColor
}
func (p *Parent) Add(c *Child) {
p.Children = append(p.Children, c)
}
func main() {
var parent Parent
var child Child
child.Age = 10
parent.Add(&child)
child.ShowHairColor = func() string {
return "red"
}
fmt.Printf("%v\n", parent.Children[0])
fmt.Printf("%v\n", child)
fmt.Println(parent.Children[0].ShowHairColor())
}
这段代码主要涉及指针的正确使用。Parent
结构体包含一个 Children
切片,Child
结构体包含一个 Age
字段和一个 ShowHairColor
函数类型的字段。Parent
结构体有一个 Add
方法,用于向 Children
切片中添加子元素。在 main
函数中,创建了一个 parent
变量和一个 child
变量。然后,将 child
的地址传递给 parent.Add
方法,将其添加到 parent.Children
切片中。接着,为 child
的 ShowHairColor
字段赋值一个返回字符串 "red" 的匿名函数。最后,打印输出了 parent.Children[0]
和 child
的值,并调用了 parent.Children[0].ShowHairColor()
方法并打印输出结果。
英文:
Ok the following works for me. The code is changed again to try to focus more clearly on the particular issue I was having. It all comes down to properly using pointers. Thanks for the suggestions.
package main
import (
"fmt"
)
type HairColor func() string
type Parent struct {
Children []*Child
}
type Child struct {
Age int
ShowHairColor HairColor
}
func (p *Parent) Add(c *Child) {
p.Children = append(p.Children, c)
}
func main() {
var parent Parent
var child Child
child.Age = 10
parent.Add(&child)
child.ShowHairColor = func() string {
return "red"
}
fmt.Printf("%v\n", parent.Children[0])
fmt.Printf("%v\n", child)
fmt.Println(parent.Children[0].ShowHairColor())
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论