golang中for range的取地址操作陷阱介紹
Tips:for range創(chuàng)建了每個(gè)元素的副本,而不是直接返回每個(gè)元素的引用
例子1:
package main
import "fmt"
func main() {
slice := []int{0, 1, 2, 3}
myMap := make(map[int]*int)
for index, value := range slice {
myMap[index] = &value
}
fmt.Println("=====new map=====")
prtMap(myMap)
}
func prtMap(myMap map[int]*int) {
for key, value := range myMap {
fmt.Printf("map[%v]=%v\n", key, *value)
}
}
輸出:
dotzdeMacBook-Pro-2:src dotz$ ./range
=====new map=====
map[0]=3
map[1]=3
map[2]=3
map[3]=3
例子2:
package main
import "fmt"
type Test struct {
name string
}
func (this *Test) Point() { // this 為指針
fmt.Println(this.name)
}
func main() {
ts := []Test{{"a"}, {"b"}, {"c"}}
for _, t := range ts {
defer t.Point() //輸出 c c c
}
}
輸出:
dotzdeMacBook-Pro-2:src dotz$ ./method
c
c
c
例子1 我們預(yù)期輸出0,1,2,3,例子2 我們預(yù)期輸出a,b, c,但兩個(gè)例子的輸出都不是我們預(yù)期的。
對(duì)于例子1,比較明顯,執(zhí)行了取地址操作,每次都取value變量的地址,所以最后map中的所有元素的值都是value變量的地址(引用),因?yàn)樽詈髒alue被賦值為3,所有輸出都是3.
對(duì)于例子2,隱晦一點(diǎn),夾雜了defer和方法接收者的規(guī)則,但其實(shí)也和例子1一樣,執(zhí)行t.Point()時(shí),得到的是t的地址(引用),for結(jié)束時(shí),t被賦值為”c“的地址,main函數(shù)返回時(shí),都在執(zhí)行”c“的接收方法Point,所以輸出都是”c".
補(bǔ)充:golang取地址操作采坑:for idx,item := range arr中的item是個(gè)獨(dú)立對(duì)象
先看代碼:
package main
import "fmt"
func main() {
type s struct {
A string
B int32
}
arr := []s{
{"123", 123},
{"456", 456},
{"789", 789},
}
m := make(map[string]*s)
for idx, item := range arr {
m[item.A] = &item
fmt.Printf("idx=%d, addr=%p, item addr=%p\n", idx, &arr[idx], &item)
}
for k, v := range m {
fmt.Printf("key=%s, v=%+v\n", k, v)
}
}
運(yùn)行輸出:
idx=0, addr=0xc00004e050, item addr=0xc0000044a0
idx=1, addr=0xc00004e068, item addr=0xc0000044a0
idx=2, addr=0xc00004e080, item addr=0xc0000044a0
key=123, v=&{A:789 B:789}
key=456, v=&{A:789 B:789}
key=789, v=&{A:789 B:789}
我傻傻的在循環(huán)中取item的地址,結(jié)果所有map中的值都指向最后一個(gè)!
看來(lái)item是一個(gè)獨(dú)立對(duì)象,這個(gè)對(duì)象指向了數(shù)組中的對(duì)應(yīng)元素。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
利用ChatGPT編寫一個(gè)Golang圖像壓縮函數(shù)
這篇文章主要為大家詳細(xì)介紹了如何利用ChatGPT幫我們寫了一個(gè)Golang圖像壓縮函數(shù),文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以嘗試一下2023-04-04
golang中byte和rune用法及新手易錯(cuò)點(diǎn)總結(jié)
golang內(nèi)置類型有rune類型和byte類型,下面這篇文章主要給大家介紹了關(guān)于golang中byte和rune用法及新手易錯(cuò)點(diǎn)總結(jié)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-03-03
go時(shí)間/時(shí)間戳操作大全(小結(jié))
這篇文章主要介紹了go時(shí)間/時(shí)間戳操作大全,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
Go語(yǔ)言中兩個(gè)比較流行的緩存庫(kù)使用示例
緩存是計(jì)算機(jī)科學(xué)中的一個(gè)重要概念,設(shè)想某個(gè)組件需要訪問(wèn)外部資源,它向外部源請(qǐng)求資源,接收并使用資源,這些步驟都需要花費(fèi)時(shí)間,下面這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言中兩個(gè)比較流行的緩存庫(kù)使用的相關(guān)資料,需要的朋友可以參考下2024-04-04

