英文:
golang append to a slice inside struct
问题
我正在尝试理解如何在Go中操作数据结构以及它对指针的处理方式(是通过复制还是引用)。
你的代码在Go Playground上,链接在这里:https://play.golang.org/p/j_06RS5Xcz
我创建了一个包含切片的结构体映射,其中结构体内部还有其他东西的切片。
代码如下:
type Item struct {
Name string
Description string
}
type Entity struct {
Base Item
Others []Item
}
var database map[int][]Entity
func main() {
database = make(map[int][]Entity)
database[1] = []Entity{}
e1 := Entity{}
e1.Base = Item{"A", "aaa"}
e1.Others = []Item{}
database[1] = append(database[1], e1)
// 后续,我想向实体添加其他项
e1.Others = append(e1.Others, Item{"B", "bbb"})
// 其他项字段为空
fmt.Println(database)
}
// 输出:map[1:[{{A aaa} []}]]
我想在程序的后续部分追加其他项。看起来我必须使用指针来解决这个问题,但我不知道该如何做。
我的Entity结构体应该像这样吗?
type Entity struct {
Base Item
Others *[]Item
}
如果是这样,我应该如何追加项呢?
*e1.Others = append(*e1.Others, Item{"B", "bbb"})
如果还有其他问题的话……我还不清楚在执行database[1] = append(database[1], e1)
之前是否必须先执行database[1] = []Entity{}
,或者在这种情况下是否可以直接追加。我尝试了在e1.Others = []Item{}
上进行相同的操作,但它没有产生相同的追加效果(我知道这是我的误解,而不是Go的问题)。
提前感谢你的帮助
英文:
I'm trying to understand how to manipulate data structures in Go, and its approach to pointers (with copies or references).
my code is on Go Playground, here: https://play.golang.org/p/j_06RS5Xcz
I made up a map of slices of a struct that also has a slice of other thing inside.
here:
type Item struct {
Name string
Description string
}
type Entity struct {
Base Item
Others []Item
}
var database map[int][]Entity
func main() {
database = make(map[int][]Entity)
database[1] = []Entity{}
e1 := Entity{}
e1.Base = Item{"A", "aaa"}
e1.Others = []Item{}
database[1] = append(database[1], e1)
// later, I want to add other items to my entity
e1.Others = append(e1.Others, Item{"B", "bbb"})
// other items field is empty
fmt.Println(database)
}
// prints: map[1:[{{A aaa} []}]]
I want to append the Others items later in my program. it seems that I must use pointers to solve this, but I don't know how.
should my Entity be like this?
type Entity struct {
Base Item
Others *[]Item
}
and if so, how should I append items to it? like this?
*e1.Others = append(*e1.Others, Item{"B", "bbb"})
.
.
.
if there is room for another question... it is also not clear to me if I 'must' do: database[1] = []Entity{}
before database[1] = append(database[1], e1)
or I could just append in this case. I tried the same on e1.Others = []Item{}
but it didn't produced the same effect to append (I know that this is my misunderstanding, not a Go's fault).
thanks in advance
答案1
得分: 2
在你当前的代码中,你有两个类型为 Entity
的对象。一个名为 e1
,另一个名为 database[1]
。由于它们是 struct
,所以这两个对象是完全独立的。因此,当你改变其中一个对象时,不会影响另一个对象。(小例外:对 Items
字段的某些更改将被共享,但不是全部。)
如果你想先将实体添加到地图中,然后再修改它,你应该使用指针的地图,即 map[int][]*Entity
。然后,你应该创建一个指向实体的指针,而不是 Entity{}
,使用 e1 := &Entity{}
,然后程序将正常工作。对 e1.Others
的更改也会影响到 database[1].Others
,因为这两个变量现在指向同一个对象。
但是 print
语句会有所不同。它不会打印结构体,而只会打印指针值。为了解决这个问题,可以添加一个 String 方法:
func (e *Entity) String() string { return fmt.Sprint(*e) }
请参考 https://play.golang.org/p/edU7E5Gnjw,我还删除了不必要的空切片。向 nil
切片追加元素是完全可以的。
如果想进一步了解,请参考 http://research.swtch.com/godata,它将回答你目前的问题。
英文:
In your current code, you have two objects of type Entity
. One is named e1
, the other is named database[1]
. These two objects are completely independent, since they are struct
s. Therefore, when you change one of them, it will not affect the other. (Small exception: some changes to the Items
field will be shared, but not all.)
If you want to first add the entity to the map and later modify it, you should use a map of pointers, map[int][]*Entity
. Then, instead of Entity{}
, you should create a pointer to an entity, with e1 := &Entity{}
, and then the program will work. The changes to e1.Others
will also affect database[1].Others
, since these two variables now point to the same object.
But the print
statement will be different. Instead of printing the struct, it will only print a pointer value. To fix this, add a String method:
func (e *Entity) String() string { return fmt.Sprint(*e) }
See https://play.golang.org/p/edU7E5Gnjw, where I also removed the needless empty slices. It is perfectly ok to append to a nil
slice.
For further reading, I suggest http://research.swtch.com/godata, which will answer the questions that you currently have.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论