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 :)
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.