for 循环迭代变量
生活随笔
收集整理的這篇文章主要介紹了
for 循环迭代变量
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
簡介
for i, v := range- i,v都是只創建一次,然后循環中賦值。
- 循環的 Map,golang為避免開發者循環時問題,所以特意在循環中打亂排序
- 循環的數組,是在開始前的鏡像,循環中添加或移除元素不改變其循環次數。
- 循環的 Map,由于其隨機特性,循環中添加或移除元素不能確定是否改變循環次數
捕獲迭代變量
這是在學習Go 程序設計中遇到的一個比較重要的一個警告。這是個 Go 語言的詞法作用域規則的陷阱??赐曛蟾杏X是真的一個比較讓人疑惑困惑的地方。所以特地記錄一下。由標題就可以知道了,迭代變量,肯定是在for中遇到的問題。來看一個簡單的例子說明一下這個問題所在。
看一段簡單的代碼, 首先是錯誤的示例:
var slice []func()func main() {sli := []int{1, 2, 3, 4, 5}for _, v := range sli {fmt.Println(&v)slice = append(slice, func(){fmt.Println(v * v) // 直接打印結果})}for _, val := range slice {val()} } // 輸出 25 25 25 25 25你可能會很奇怪為什么會出現這種情況,結果不應該是1, 4, 9, 16, 25嗎?其實原因是循環變量的作用域的規則限制。在上面的程序中,v在 for 循環引進的一個塊作用域內進行聲明。在循環里創建的所有函數變量共享相同的變量,就是一個可訪問的存儲位置,而不是固定的值。(你會驚奇的發現&v的內存地址是一樣的)
模擬一下實際的情況,假設 v 變量的地址在 0x12345678 上, for 循環在迭代過程中,所有變量值都是在這地址上迭代的。當最后調用匿名函數的時候,取值也是在這塊地址上。所以最后輸出的結果都是迭代的最后一個值。至少在 Go 語言中是不用質疑的。這里也是一個陷阱,如果你不清楚的話,肯定會遇到坑。那個該如何修改呢?
var slice []func()func main() {sli := []int{1, 2, 3, 4, 5}for _, v := range sli {temp := v // 其實很簡單 引入一個臨時局部變量就可以了,這樣就可以將每次的值存儲到該變量地址上fmt.Println(&temp) // 這里內存地址是不同的slice = append(slice, func(){fmt.Println(temp * temp) // 直接打印結果})}for _, val := range slice {val()} } // 輸出 1, 4, 9, 16, 25 預期結果只需要引入一個局部變量便可以解決了,這是必須的。否則你的程序將不會有可預期的結果
總結
以上是生活随笔為你收集整理的for 循环迭代变量的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: golang常用技巧
- 下一篇: 协程和纤程