go語言循環與指針陷阱:詳解v.name全為“博客”的原因
Go語言中的for…range循環和指針結合使用時,容易出現一些令人困惑的問題。本文通過一個例子,深入剖析for…range循環的機制以及指針的使用,解釋為什么代碼輸出結果全為“博客”。
以下代碼片段展示了這個問題:
type student struct { name string age int } func main() { m := make(map[string]*student) stus := []student{ {name: "pprof.cn", age: 18}, {name: "測試", age: 23}, {name: "博客", age: 28}, } for _, stu := range stus { m[stu.name] = &stu // 問題出在這里 } for k, v := range m { fmt.Println(k, "=>", v.name) } }
運行這段代碼,輸出結果將全部是博客。這是因為for…range循環中的stu變量并非每次迭代都創建一個新的變量。它是一個循環變量,其內存地址在整個循環過程中保持不變。 因此,&stu始終指向同一個內存地址。每次迭代都將這個相同的地址賦值給map中的值,最終map中所有指針都指向了最后一個stu變量,即{name: “博客”, age: 28}。
解決方法:創建新的變量副本
立即學習“go語言免費學習筆記(深入)”;
為了避免這個問題,需要在每次迭代中創建stu的副本,而不是直接使用其地址:
for _, stu := range stus { s := stu // 創建stu的副本 m[stu.name] = &s }
通過創建新的變量s,m[stu.name] = &s 現在指向的是s的內存地址,而s在每次迭代中都是一個新的變量,從而解決了指針指向同一內存地址的問題,最終輸出結果將正確反映每個學生的姓名。
理解for…range循環的機制以及指針的特性,對于編寫高效且正確的Go代碼至關重要。 避免此類陷阱的關鍵在于,在循環中使用指針時,要確保每個指針都指向不同的內存地址。
? 版權聲明
文章版權歸作者所有,未經允許請勿轉載。
THE END
喜歡就支持一下吧
相關推薦