Tips:for range創建了每個元素的副本,而不是直接返回每個元素的引用
例子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,比較明顯,執行了取地址操作,每次都取value變量的地址,所以最后map中的所有元素的值都是value變量的地址(引用),因為最后value被賦值為3,所有輸出都是3.
對于例子2,隱晦一點,夾雜了defer和方法接收者的規則,但其實也和例子1一樣,執行t.Point()時,得到的是t的地址(引用),for結束時,t被賦值為”c“的地址,main函數返回時,都在執行”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}
我傻傻的在循環中取item的地址,結果所有map中的值都指向最后一個!
看來item是一個獨立對象,這個對象指向了數組中的對應元素。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
您可能感興趣的文章:- 基于golang中container/list包的用法說明
- Golang中List的實現方法示例詳解
- golang使用grpc+go-kit模擬oauth認證的操作
- golang如何去除多余空白字符(含制表符)
- 用golang如何替換某個文件中的字符串
- golang正則之命名分組方式
- 解決golang中container/list包中的坑