Loops 循环和映射引用
我的代码在Loops 循环和映射引用,loops,pointers,go,Loops,Pointers,Go,我的代码在Task数组上循环,并使用字符串键和Task值创建一个映射: package main import ( "fmt" ) type Task struct { Name string Project string } func main() { taskMap := map[string]*Task{} taskList := []Task{ { Name: "name1",
Task
数组上循环,并使用字符串键和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,
}
}
因此,最后访问的任务的引用显然存储在taskMap
的每个键中
有没有一种方法可以做到这一点而不必手动复制每个字段?所有键的值都相同,因为您在
for
循环中引用了相同的任务
变量。使用以下代码段获取对切片中项目的引用
for idx, task := range taskList {
taskMap[task.Name] = &taskList[idx]
}
顺便说一句,要复制一个变量,您可以将其分配给一个新变量,如
for _, task := range taskList {
x := task
taskMap[task.Name] = &x
}
每次迭代都将创建一个新的
x
变量,并在映射内使用指向该变量的指针。所有键的值都相同,因为您在循环中引用了相同的任务
变量。使用以下代码段获取对切片中项目的引用
for idx, task := range taskList {
taskMap[task.Name] = &taskList[idx]
}
顺便说一句,要复制一个变量,您可以将其分配给一个新变量,如
for _, task := range taskList {
x := task
taskMap[task.Name] = &x
}
每次迭代将创建一个新的x
变量,并在映射中使用指向该变量的指针。您存储的是任务的地址,而不是值
您可以将taskList
切换到一段指针:taskList:=[]*Task{
并使用taskMap[Task.Name]=Task
存储的是Task
的地址,而不是值
您可以将taskList
切换到一段指针:taskList:=[]*Task{
并使用taskMap[Task.Name]=任务
事实上我比我更喜欢Arman的答案,它向你展示了如何在不改变现有数据结构的情况下完成它。在这种情况下,我的答案是可以接受的,但你不能总是控制输入的内容。事实上,我比我更喜欢Arman的答案,它向你展示了如何在不改变现有数据结构的情况下完成它。我的答案是在这种情况下是可接受的,但您并不总是控制输入的内容。变量task
存储在每次迭代中更改的本地副本,但task
的地址(存储在映射中)保持不变。因此,当您打印地图内容时,所有地图值都指向最后一个列表项的副本。变量task
存储在每次迭代中更改的本地副本,但task
的地址(存储在地图中)保持不变。因此,当您打印映射内容时,所有映射值都指向最后一个列表项的副本。对于I:=range taskList{taskMap[taskName]=&taskList[I]},正确的解决方案应该是
。我的意思是,如果想在每次迭代中获得一个指向切片元素的指针,那么获取元素本身就没有意义了——它的索引就足够了,并且可以轻松地使用它来获取指向其对应元素的指针。除了在您的示例中,taskName
不存在之外;您需要元素来获取名称。在我看来,发布的解决方案似乎是正确的。“让它存在”并不难不,真的。ooo或者你可以只使用范围
运算符的两个参数形式,而不必使用中间变量或额外的切片标识符。说真的,为什么要让这比需要的更难呢。两个参数形式在这里非常合适。我想说,对于I:=范围任务列表,正确的解决方案应该是{taskMap[taskName]=&taskList[i]}
。我的意思是,如果想在每次迭代中获得一个指向切片元素的指针,那么获取元素本身就没有意义了——它的索引就足够了,并且可以轻松地使用它来获取指向其对应元素的指针。除了在您的示例中,taskName
不存在之外;您需要元素来获取名称。在我看来,发布的解决方案似乎是正确的。“让它存在”并不难。不,真的。ooo或者您可以只使用range
运算符的双参数形式,而不必使用中间变量或附加的切片标识符。说真的,为什么要让这比需要的更难呢。双参数形式在这里非常合适。