Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pointers 在循环中重置指针_Pointers_Go - Fatal编程技术网

Pointers 在循环中重置指针

Pointers 在循环中重置指针,pointers,go,Pointers,Go,这个问题暴露了我对Golang指针(或任何指针,真的)的基本理解不足,所以请容忍我。如果有帮助的话,我也在围棋场上举了一个类似的工作示例: 假设我有两个结构的基本父/子关系: //Parent type User struct{ ID int Rsvps []*Rsvp } //Child type Rsvp struct{ Response string } 在某种程度上,会创建一组用户和RSVP,并将信息存储在数据库中。在某个时刻,从数据库中提取信息并将

这个问题暴露了我对Golang指针(或任何指针,真的)的基本理解不足,所以请容忍我。如果有帮助的话,我也在围棋场上举了一个类似的工作示例:

假设我有两个结构的基本父/子关系:

//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)

}

为了使问题简洁明了,我应该如何迭代一个数据集,将项目收集到一个片段中,然后将该片段写入一个唯一的内存点,以便下一组迭代不会覆盖它?

如何执行以下操作:

    package main

    import (
        "fmt"
    )

    type User struct {
        ID    int
        Rsvps []*Rsvp
    }

    type Rsvp struct {
        Response string
    }

    func main() {
        users := []int{1, 2, 3}
        responses := []string{"Yes", "No", "Maybe"}
        var results []*User
        for _, i := range users {
            r := Rsvp{Response: responses[i-1]} // create new variable
            u := User{ID: i}
            u.Rsvps = append(u.Rsvps, &r)
            results = append(results, &u)
        }
        for _, r := range results {
            fmt.Println(r.ID, r.Rsvps[0].Response)
        }

    }

我以您的游乐场为例,删除注释并更改代码以获得所需的输出。主要的变化是我不再重复使用
r
。最初您总是附加
&r
,但在循环开始时更改
r
。当然,这会改变r指向的内存,使所有内容都成为
可能
问题不是由指向
Rsvp
的指针引起的,而是以下语句:

在每次迭代过程中,变量
user
的值被覆盖,但由于变量
user
是在循环外部定义的,因此变量
user
(即
&user
)的地址将保持不变。因此,
结果
切片中的元素将是相同的,即单个
用户的地址
变量,其中的值是从最后一条记录中捕获的。将
append
语句更改为:

//result = append(result, &user)
u := user
result = append(result, &u)

可以在以下位置找到演示此问题的最低示例。

每个变量都会写入自己的内存。如果希望某个变量在循环的作用域(或任何块)之外持续存在,请在该块之外声明该变量。是。我想这就是我在做的,除非我误解了你的解决方案。我将指针切片变量设置在循环范围之外,只是为了观察它在每次迭代时被重写。哪个变量被重写了?我真的不知道您打算在这个示例中做什么。我建议停止尝试在作用域之间共享数据,并将其重构为一些返回您感兴趣的数据的函数。。。基于psuedocode,我认为它看起来基本正确,但它告诉我们的东西很少。如果你能发表一篇文章,我们可能会提供更多的见解。谢谢。在游乐场示例中,我没有捕捉到我试图为一个用户收集多个RSVP的问题。我需要一些方法在循环之前定义一个片段,然后在循环期间为一个用户收集所有RSVP,然后在循环遇到新用户时将收集的RSVP分配给用户。天哪,这是一个多么“简单”的答案。非常感谢。只需将变量设置为另一个“fresh”变量以保留它,然后将该变量附加到切片。明亮的与此同时,我刚刚准备了一份MCVE,以防有人(现在)对学术感兴趣:
//result = append(result, &user)
u := user
result = append(result, &u)