Go語言中的for…range循環與map數據結構結合使用時,容易出現一個常見的陷阱:當遍歷切片并將元素添加到map中時,所有map的值最終都指向最后一個元素。本文將通過代碼示例分析其原因,并提供解決方案。
讓我們來看一段代碼:
type Student struct { Name string Age int } func main() { m := make(map[string]*Student) students := []Student{ {Name: "pprof.cn", Age: 18}, {Name: "測試", Age: 23}, {Name: "博客", Age: 28}, } for _, stu := range students { m[stu.Name] = &stu // 問題出在這里 } for k, v := range m { fmt.Println(k, "=>", v.Name) } }
這段代碼的預期結果是將students切片中的每個Student結構體存儲到map中。然而,運行結果卻顯示所有map的值都指向最后一個元素“博客”:
立即學習“go語言免費學習筆記(深入)”;
pprof.cn => 博客 測試 => 博客 博客 => 博客
問題根源:for…range循環的變量作用域
問題在于for…range循環中,stu變量并非每次迭代都創建一個新的變量。它指向的是students切片中同一個內存地址。每次迭代,stu的值都會被更新,但其內存地址保持不變。因此,當循環結束后,map中的所有指針都指向stu的最終值(最后一個元素)。
解決方案:創建新的變量副本
為了解決這個問題,我們需要在每次迭代中創建一個stu變量的副本,確保map中存儲的是不同的內存地址。修改后的代碼如下:
for _, stu := range students { newStu := stu // 創建副本 m[newStu.Name] = &newStu }
或者,更簡潔的方法是直接創建新的Student結構體:
for _, stu := range students { m[stu.Name] = &Student{Name: stu.Name, Age: stu.Age} // 創建新的Student實例 }
通過以上修改,map中的每個值將指向不同的內存地址,從而避免了所有值都指向最后一個元素的情況。 運行修改后的代碼將得到預期的結果。
希望這個解釋能夠幫助您理解Go語言中for…range循環和map數據結構的細節,并避免此類陷阱。
? 版權聲明
文章版權歸作者所有,未經允許請勿轉載。
THE END
喜歡就支持一下吧
相關推薦