golang中for range的取地址操作陷阱介紹
Tips:for range創(chuàng)建了每個元素的副本,而不是直接返回每個元素的引用
例子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 我們預期輸出0,1,2,3,例子2 我們預期輸出a,b, c,但兩個例子的輸出都不是我們預期的。
對于例子1,比較明顯,執(zhí)行了取地址操作,每次都取value變量的地址,所以最后map中的所有元素的值都是value變量的地址(引用),因為最后value被賦值為3,所有輸出都是3.
對于例子2,隱晦一點,夾雜了defer和方法接收者的規(guī)則,但其實也和例子1一樣,執(zhí)行t.Point()時,得到的是t的地址(引用),for結(jié)束時,t被賦值為”c“的地址,main函數(shù)返回時,都在執(zhí)行”c“的接收方法Point,所以輸出都是”c".
補充:golang取地址操作采坑:for idx,item := range arr中的item是個獨立對象
先看代碼:
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) } }
運行輸出:
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中的值都指向最后一個!
看來item是一個獨立對象,這個對象指向了數(shù)組中的對應(yīng)元素。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
Golang?sync.Once實現(xiàn)單例模式的方法詳解
Go?語言的?sync?包提供了一系列同步原語,其中?sync.Once?就是其中之一。本文將深入探討?sync.Once?的實現(xiàn)原理和使用方法,幫助大家更好地理解和應(yīng)用?sync.Once,需要的可以參考一下2023-05-05更高效的GoLevelDB:shardingdb實現(xiàn)分片和并發(fā)讀寫操作
這篇文章主要介紹了更高效的GoLevelDB:shardingdb實現(xiàn)分片和并發(fā)讀寫操作的相關(guān)資料,需要的朋友可以參考下2023-09-09Golang WebView跨平臺的桌面應(yīng)用庫的使用
Golang WebView是一個強大的桌面應(yīng)用庫,本文介紹了Golang WebView的特點和使用方法,并列舉示例詳細的介紹了其在實際項目中的應(yīng)用,具有一定的參考價值,感興趣的可以了解一下2024-03-03Golang實現(xiàn)Json分級解析及數(shù)字解析實踐詳解
你是否遇到過在無法準確確定json層級關(guān)系的情況下對json進行解析的需求呢?本文就來和大家介紹一次解析不確定的json對象的經(jīng)歷,以及遇到的問題和解決方法2023-02-02淺析Go中fasthttp與net/http的性能對比及應(yīng)用
這篇文章主要為大家詳細介紹了Golang中fasthttp的底層實現(xiàn)以及與net/http的區(qū)別,下面就跟隨小編一起來看看fasthttp到底是如何做到性能如此之快的吧2024-03-03