无法获取地图元素的地址

我想知道为什么

x:= odsMap[segRef]
x.GetValue("@OriginDestinationKey")

有效,但这不起作用:

odsMap[segRef].GetValue("@OriginDestinationKey")

?

最后一个片段打印以下错误:

cannot call pointer method on odsMap[segRef]go
cannot take the address of odsMap[segRef]

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

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

谢谢。


HUX布斯
浏览 114回答 2
2回答

白板的微信

映射索引表达式是不可寻址的,因为当向映射添加新条目时,映射的内部可能会发生变化,因此规范故意不允许获取其地址(这为映射实现提供了更大的自由度)。这意味着如果您在映射中存储非指针,并且想要调用具有指针接收器的存储值的方法,则需要获取非指针值的地址(用作接收器) ,但由于映射索引表达式不可寻址,因此会导致编译时错误。解决方法是将指针值存储在映射中,因此不需要获取索引表达式的地址,因为它已经是一个指针。在这个答案中可以看到这样的一个例子:Why should constructor of Go return address? 如果我们有这种类型:type My intfunc (m *My) Str() string { return strconv.Itoa(int(*m)) }这给出了相关的编译时错误:m := map[int]My{0: My(12)}m[0].Str() // Error!但这有效:m := map[int]*My{}my := My(12)m[0] = &my // Store a pointer in the mapm[0].Str() // You can call it, no need to take the address of m[0]           // as it is already a pointer另一种选择是将其分配给一个可以获取其地址的局部变量,并对其调用指针方法。但必须小心,就像该方法具有指针接收器一样,它可能会修改指向的对象或其组件(例如结构体的字段),这不会反映在存储在映射中的值中。如果您沿着这条路径走下去,您可能必须将值重新分配给映射中的键才能获得更新的值。总而言之,如果您的值的类型具有带有指针接收器的方法,那么最好将其(存储、传递)用作指针而不是非指针值。

慕尼黑5688855

下面是一个示例,说明“值接收器”与“指针接收器”如何与“指针映射”与“值映射”交互:https://play.golang.org/p/JVp6DirgPkUpackage mainimport (    "fmt")// a simple type, with two methods : one with a value receiver, one with a pointer receivertype Item struct {    name string}func (i Item) GetNameByValue() string {    return i.name}func (i *Item) GetNameByRef() string {    return i.name}func main() {    {        // in this map, we store *pointers* to Item values        mapByRef := make(map[int]*Item)        mapByRef[0] = &Item{"I am stored as a pointer"}        // GetNameByRef will work on a *Item : "mapByRef[0]" is already a pointer        fmt.Println("GetByRef   :", mapByRef[0].GetNameByRef())        // GetNameByValue will work on a *Item :   go automatically turns this into '(*mapByRef[0]).GetNameByValue()', and this is valid        fmt.Println("GetByValue :", mapByRef[0].GetNameByValue())    }    {        // in this map, we store Item values (no pointers)        mapByValue := make(map[int]Item)        mapByValue[0] = Item{"I am stored as a value"}        // GetNameByValue will work on a Item :  "mapByValue[0]" has the right type        fmt.Println("GetByValue :", mapByValue[0].GetNameByValue())        // GetNameByRef will not work :  go tries to turn this into :  (&mapByValue[0]).GetNameByRef(),        // and go refuses to let you take the address of a value inside a map        // fmt.Println("GetByRef   :", mapByValue[0].GetNameByRef())        // compiler error :        //   ./prog.go:47:46: cannot call pointer method on mapByValue[0]        //   ./prog.go:47:46: cannot take the address of mapByValue[0]        // you will need some way to copy the value before taking its address :        item := mapByValue[0]        fmt.Println("item.GetByRef    :", item.GetNameByRef())        // same as :        fmt.Println("(&item).GetByRef :", (&item).GetNameByRef())    }}// Output ://// GetByRef   : I am stored as a pointer// GetByValue : I am stored as a pointer// GetByValue : I am stored as a value// item.GetByRef    : I am stored as a value// (&item).GetByRef : I am stored as a value
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go