无法获取地图元素的地址

Elo*_*nco 0 methods dictionary pointers go

我想找出原因

x:= odsMap[segRef]
x.GetValue("@OriginDestinationKey")
Run Code Online (Sandbox Code Playgroud)

可以,但是不能:

odsMap[segRef].GetValue("@OriginDestinationKey")
Run Code Online (Sandbox Code Playgroud)

最后一个代码段显示以下错误:

cannot call pointer method on odsMap[segRef]go
cannot take the address of odsMap[segRef]
Run Code Online (Sandbox Code Playgroud)

这些错误发生在编译时(而不是运行时)。所以,我的主要问题是为什么我需要一个中间变量x来访问该函数?

关于变量的类型odsMapmap[string]XMLElement并且segRef是字符串。

谢谢。

icz*_*cza 6

映射索引表达式不可寻址,因为当向其添加新条目时,映射的内部可能会更改,因此规范有意不允许使用其地址(这为映射实现提供了更大的自由度)。

这意味着,如果您将非指针存储在映射中,并且要调用具有指针接收器的存储值的方法,则需要获取非指针值的地址(用作接收器) ,但由于映射索引表达式不可寻址,因此会导致编译时错误。

一种解决方法是将指针值存储在映射中,因此无需获取索引表达式的地址,因为它已经是一个指针。可以在以下答案中看到一个示例:为什么Go的构造函数应返回地址?如果我们有这种类型:

type My int

func (m *My) Str() string { return strconv.Itoa(int(*m)) }
Run Code Online (Sandbox Code Playgroud)

这给出了相关的编译时错误:

m := map[int]My{0: My(12)}
m[0].Str() // Error!
Run Code Online (Sandbox Code Playgroud)

但这有效:

m := map[int]*My{}
my := My(12)
m[0] = &my // Store a pointer in the map

m[0].Str() // You can call it, no need to take the address of m[0]
           // as it is already a pointer
Run Code Online (Sandbox Code Playgroud)

另一种选择是将其分配给可以获取其地址的局部变量,然后在该变量上调用指针方法。尽管必须小心,就像该方法具有指针接收器一样,它可能会修改指向的对象或其组件(例如,结构的字段),而这不会反映在映射中存储的值中。如果沿着这条路径前进,则可能必须将值重新分配给映射中的键才能获得更新的值。

总而言之,如果您的值的类型具有使用指针接收器的方法,则最好将其(存储,传递)用作指针,而不是用作非指针值。

查看相关问题:

非指针类型的指针方法

如何在Go中存储对操作结果的引用?