这个问题背离了我对Golang指针(或者任何指针)的基本理解,所以请耐心等待。我也提出了类似的,工作例如在去游乐场,如果它是有帮助的:重置循环中的指针
https://play.golang.org/p/Xe-ZRdFWGp
假设我有两个结构基本父/子关系:
//Parent
type User struct{
ID int
Rsvps []*Rsvp
}
//Child
type Rsvp struct{
Response string
}
在一些点,创建了一堆用户和RSVP,并将信息存储在数据库中。在某个时候,它将来到从该数据库提取信息并将其写回到这些结构中的时间。在使用关系数据库时,我通常会尝试使用单个查询来做到这一点,这种模式我已经使用了很多年了,但这可能不再是正确的方式。我将设置一个循环来提取数据。下面是一些伪代码有许多评论:
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)
}
为了使问题简洁,并希望清楚,我怎么通过数据集进行迭代,收集项目成片,然后写切片成一个独特的记忆点,使得下一组迭代不会覆盖它?
每个变量都写入自己的内存中。如果你想让一个变量在一个循环的作用域(或任何块)之外持久化,则在该块之外声明该变量。 – Adrian
是的。我认为这就是我所做的,除非我误解了你的解决方案。我将指针切片变量设置在循环范围之外,只是为了观察它在每次迭代时被重写。 – Brent
哪个变量被覆盖? – Adrian