This question betrays my basic lack of understanding of Golang pointers (or any pointer, really), so please bear with me. I've also put a similar, working example on Go Playground if it's helpful:
https://play.golang.org/p/Xe-ZRdFWGp
Suppose that I have a basic parent/child relationship with two structs:
//Parent
type User struct{
ID int
Rsvps []*Rsvp
}
//Child
type Rsvp struct{
Response string
}
At some point, a bunch of users and RSVPs is created, and the information stored in a database. At some point, it will come time to extract information from that database and write it back into these structs. When using a relational database, I'll typically try to do it with a single query, in a pattern I've been using for many years, but which may not be the right way any more. I'll to set up a loop to extract the data. Here's some pseudocode with many comments:
func getUsersAndRsvps() []*User{
sql := "SELECT * FROM users LEFT JOIN rsvps ON users.field1 = rsvps.field1 ORDER BY user.ID;"
dataset := getDataset(sql)
result = []*User{}
rsvps = []*Rsvp{}
//Oh, but you already see the problem here, don't you! I'm defining
//rsvps outside of the loop, and the values contained at its address
//will become values for all users, instead of per user. Yet, how
//else can I collect together rsvps while iterating?
user = User{} //hold onto a user while iterating
lastUserID := int64(0) //track when we move from one user to the next
for _, record := range dataset{
thisUserID := record.ID
//When this user is different from last user
//take the collected rsvps and write them into
//the (old) user, then continue iterating...
if lastUserID != thisUserID && lastUserID > 0{
//So, right here is the big problem. I'm writing
//the address of collected rsvps into the previous user record.
//However, on each iteration, that address gets all
//new info, such that at the end of the readout,
//all users have the same rsvps.
user.Rsvps = rsvps
result = append(result, &user)
//So, yes, I "blank out" the rsvps, but that only goes
//to make the last user's rsvps be those shared among all
rsvps = []*Rsvp{}
}
//Gather rsvps
rsvp = getRsvp(rsvp) //defined elsewhere
rsvps = append(rsvps, &rsvp)
user = getUser(record) //defined elsewhere
lastUserID := thisUserID
}
//Capture last record
user.Rsvps = rsvps
result = append(result, &user)
}
To make the question succinct and hopefully clear, how do I iterate through a dataset, collecting items into a slice, and then write that slice into a unique memory point such that the next set of iterations won't overwrite it?