循环和地图参考

Ser*_*lla 0 pointers loops go

我有代码循环数组Task并使用字符串键和Task值创建一个Map :

package main

import (
    "fmt"
)

type Task struct {
    Name    string
    Project string
}

func main() {
    taskMap := map[string]*Task{}
    taskList := []Task{
        {
            Name:    "name1",
            Project: "project1",
        },
        {
            Name:    "name2",
            Project: "project2",
        },
        {
            Name:    "name3",
            Project: "project3",
        },
    }
    for _, task := range taskList {
        taskMap[task.Name] = &task
    }

    // Print results
    for k, v := range taskMap {
        fmt.Println(k, v)
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码的输出如下:

name1 &{name3 project3}
name2 &{name3 project3}
name3 &{name3 project3}
Run Code Online (Sandbox Code Playgroud)

这不是我的预期,因为它每次都打印相同.我对这里发生了什么有一点线索,因为如果我用以下代码替换循环,它会按预期工作:

for _, task := range taskList {
        taskMap[task.Name] = &Task{
            Name:        task.Name,
            Project: task.Project,
        }
}
Run Code Online (Sandbox Code Playgroud)

因此,某种程度上对最后访问的任务的引用是最终存储在每个键中的任务taskMap,显然.

有没有办法这样做而不必手动复制每个字段?

Arm*_*ani 5

您获得所有键的相同值,因为您taskfor循环中引用相同的变量.使用以下代码段获取对切片中项目的引用.

for idx, task := range taskList {
    taskMap[task.Name] = &taskList[idx]
}
Run Code Online (Sandbox Code Playgroud)

BTW(浅)复制变量,你可以将它分配给一个新的变量,如

for _, task := range taskList {
    x := task
    taskMap[task.Name] = &x
}
Run Code Online (Sandbox Code Playgroud)

x将在每次迭代中创建一个新变量,并在地图内使用指向该变量的指针.