循环和地图参考

时间:2017-12-05 13:39:35

标签: loops pointers go

我的代码循环遍历-S数组,并创建一个包含字符串键和Task值的Map:

Task

此代码的输出如下:

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

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

name1 &{name3 project3}
name2 &{name3 project3}
name3 &{name3 project3}

所以不知何故,对上次访问的任务的引用显然是存储在for _, task := range taskList { taskMap[task.Name] = &Task{ Name: task.Name, Project: task.Project, } } 的每个键中的任务。

有没有办法在不借助手动复制每个字段的情况下执行此操作?

2 个答案:

答案 0 :(得分:5)

您获得所有密钥的相同值,因为您在into_inner循环中引用了相同的task变量。使用以下代码段来获取对切片中项目的引用。

for

BTW(浅)复制变量,您可以将其分配给新变量,如

for idx, task := range taskList {
    taskMap[task.Name] = &taskList[idx]
}

将在每次迭代中创建一个新的for _, task := range taskList { x := task taskMap[task.Name] = &x } 变量,并在地图中使用指向该变量的指针。

答案 1 :(得分:0)

您正在存储task的地址而不是值。

您可以改为将taskList切换为一片指针:taskList := []*Task{并使用taskMap[task.Name] = task