亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

無法獲取地圖元素的地址

無法獲取地圖元素的地址

Go
HUX布斯 2023-07-10 14:42:05
我想知道為什么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來訪問該函數?關于變量的類型odsMap是map[string]XMLElement 并且segRef是字符串。謝謝。
查看完整描述

2 回答

?
白板的微信

TA貢獻1883條經驗 獲得超3個贊

映射索引表達式是不可尋址的,因為當向映射添加新條目時,映射的內部可能會發生變化,因此規范故意不允許獲取其地址(這為映射實現提供了更大的自由度)。


這意味著如果您在映射中存儲非指針,并且想要調用具有指針接收器的存儲值的方法,則需要獲取非指針值的地址(用作接收器) ,但由于映射索引表達式不可尋址,因此會導致編譯時錯誤。


解決方法是將指針值存儲在映射中,因此不需要獲取索引表達式的地址,因為它已經是一個指針。在這個答案中可以看到這樣的一個例子:Why should constructor of Go return address? 如果我們有這種類型:


type My int


func (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 map


m[0].Str() // You can call it, no need to take the address of m[0]

           // as it is already a pointer

另一種選擇是將其分配給一個可以獲取其地址的局部變量,并對其調用指針方法。但必須小心,就像該方法具有指針接收器一樣,它可能會修改指向的對象或其組件(例如結構體的字段),這不會反映在存儲在映射中的值中。如果您沿著這條路徑走下去,您可能必須將值重新分配給映射中的鍵才能獲得更新的值。


總而言之,如果您的值的類型具有帶有指針接收器的方法,那么最好將其(存儲、傳遞)用作指針而不是非指針值。


查看完整回答
反對 回復 2023-07-10
?
慕尼黑5688855

TA貢獻1848條經驗 獲得超2個贊

下面是一個示例,說明“值接收器”與“指針接收器”如何與“指針映射”與“值映射”交互:

https://play.golang.org/p/JVp6DirgPkU

package main


import (

    "fmt"

)


// a simple type, with two methods : one with a value receiver, one with a pointer receiver

type 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


查看完整回答
反對 回復 2023-07-10
  • 2 回答
  • 0 關注
  • 154 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號