2 回答

TA貢獻1862條經驗 獲得超7個贊
方法 1 中的問題是您沒有獲取字符串的地址,而是獲取了它所在變量的地址。在 Go 中,&v返回變量的地址v。當你有這樣的循環時:
for k, v := range aMap {
...
}
您在循環開始時聲明的變量k和v在整個循環中使用的變量是相同的。它們只是在每次迭代中被分配了不同的值。在該循環中,&v總是計算出相同的值: 的地址v。這就是為什么您的所有地圖條目都出現在"foo":"foo"中的最后一個值v,并且它仍然存在。
您可以通過更改字符串值來查看此行為。所有的地圖鍵都會改變:
*bMap["foo"] = "quux"
fmt.Println(*bMap["bar"]) // prints "quux"
方法 2 有效,因為函數的每次調用都有自己的局部變量。Go 保證,如果您從函數返回局部變量的地址,該變量將被分配在堆上,只要需要它就可以使用它。所以你的輔助函數告訴 Go 分配一個新string變量,將傳入的字符串復制到它,然后返回它的地址。
這是另一種可行的方法:
dMap := make(map[string]*string)
for k, v := range(aMap){
dMap[k] = new(string)
*dMap[k] = v
}
這會分配一個新的字符串變量,將其地址保存在映射中,然后將 v 復制到其中。如果您要經常這樣做,輔助函數可能是最好的。
您嘗試的代碼如下:
v := "foo"
val := *v
bMap[key] = &val
不起作用,因為您說“v 是一個字符串;現在將字符串指向的值存儲在 val 中”,但該字符串不是指針。

TA貢獻1854條經驗 獲得超8個贊
問題中的第一種方法使用v所有鍵的單個循環變量的地址。您看到的值是最后一個設置為 的值v。
通過為每次迭代聲明一個新變量并獲取該變量的地址來修復。
bMap := make(map[string]*string)
for k, v := range aMap {
v := v // declare new variable v initialized with value from outer v
bMap[k] = &v
}
問題中的第二種方法還為循環中的每次迭代聲明了一個新變量。新變量是函數參數。
這個答案顯示了解決這個問題的慣用方法。請參閱Go 常見問題解答:作為 goroutine 運行的閉包會發生什么?在閉包和 goroutine 的上下文中討論相同的問題。
- 2 回答
- 0 關注
- 159 瀏覽
添加回答
舉報