将指针值重写为结构体时,将其附加到切片结构体中。

huangapple go评论90阅读模式
英文:

Pointer values rewritten in struct when appending to slice struct

问题

我今天遇到了一个奇怪的问题。

我一直在尝试从一个映射中获取值,并将其赋给一个结构体类型变量的切片。但是不知何故,结构体键中的指针值被重写了,原因不明。我编写了一个示例代码来演示这个问题。

package main

import "fmt"

type PType []struct {
	Main  string
	PVals *[]string
}

var mkey = map[string][]string{
	"xpos": {"123", "234", "543"},
	"ypos": {"-12", "9", "0"},
}

func main() {
	var db PType
	for mval, pval := range mkey {
		db = append(db, struct {
			Main  string
			PVals *[]string
		}{
			Main:  mval,
			PVals: &pval,
		})
	}
	for _, x := range db {
		fmt.Printf("Main: %+v | PVal: %+v\n", x.Main, x.PVals)
	}
}

在结构体db中,键PVals的值在内存中被某种方式重写,导致输出为:

Main: xpos | PVal: &[-12 9 0]
Main: ypos | PVal: &[-12 9 0]

...理想情况下应该是

Main: xpos | PVal: &[123 234 543]
Main: ypos | PVal: &[-12 9 0]

如果我将PType.PVals的类型从*[]string更改为[]string,问题就会得到解决。

在使用指针时,我做错了什么?

这是一个Playground链接,如果有帮助的话:https://play.golang.org/p/IVOUfTvoLt6

英文:

I've been dealing with a weird issue today.

So, I've been trying to get values from a map and assign to a slice of struct type variable. But somehow the pointer value in a struct key gets rewritten, not sure why. I've written a sample code to demonstrate the problem.

package main

import "fmt"

type PType []struct {
	Main  string
	PVals *[]string
}

var mkey = map[string][]string{
	"xpos": {"123", "234", "543"},
	"ypos": {"-12", "9", "0"},
}

func main() {
	var db PType
	for mval, pval := range mkey {
		db = append(db, struct {
			Main  string
			PVals *[]string
		}{
			Main:  mval,
			PVals: &pval,
		})
	}
	for _, x := range db {
		fmt.Printf("Main: %+v | PVal: %+v\n", x.Main, x.PVals)
	}
}

The value of the key PVals in the struct db gets overwritten somehow in memory resulting in the output:

Main: xpos | PVal: &[-12 9 0]
Main: ypos | PVal: &[-12 9 0]

...which should ideally be

Main: xpos | PVal: &[123 234 543]
Main: ypos | PVal: &[-12 9 0]

The problem is fixed if I change the type of the PType.PVals from *[]string to just []string.

What am I doing wrong keeping pointers?

Here a playground link if that helps: https://play.golang.org/p/IVOUfTvoLt6

答案1

得分: 4

在一个for循环中,循环变量的地址是固定的。每次迭代都会重写循环变量。当你在映射中添加循环变量的地址时,你实际上添加的是在每次迭代中被重写的相同片段。因此,你最终得到的是一个值指向相同位置的映射。

如果没有指针,循环变量的副本将被放置在映射中。

英文:

In a for loop, the addresses of the loop variables are fixed. Every iteration rewrites the loop variables. When you add the address of the loop variable in the maps, you add the same slice that gets overwritten at each iteration. So you end up with a map whose values are pointing to the same location.

Without the pointer, a copy of the loop variable is placed in the map.

huangapple
  • 本文由 发表于 2021年8月31日 22:08:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/69000244.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定