日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

for 循环迭代变量

發(fā)布時(shí)間:2025/6/15 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 for 循环迭代变量 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

簡(jiǎn)介

for i, v := range
  • i,v都是只創(chuàng)建一次,然后循環(huán)中賦值。
  • 循環(huán)的 Map,golang為避免開(kāi)發(fā)者循環(huán)時(shí)問(wèn)題,所以特意在循環(huán)中打亂排序
  • 循環(huán)的數(shù)組,是在開(kāi)始前的鏡像,循環(huán)中添加或移除元素不改變其循環(huán)次數(shù)。
  • 循環(huán)的 Map,由于其隨機(jī)特性,循環(huán)中添加或移除元素不能確定是否改變循環(huán)次數(shù)

捕獲迭代變量

這是在學(xué)習(xí)Go 程序設(shè)計(jì)中遇到的一個(gè)比較重要的一個(gè)警告。這是個(gè) Go 語(yǔ)言的詞法作用域規(guī)則的陷阱。看完之后感覺(jué)是真的一個(gè)比較讓人疑惑困惑的地方。所以特地記錄一下。由標(biāo)題就可以知道了,迭代變量,肯定是在for中遇到的問(wèn)題。來(lái)看一個(gè)簡(jiǎn)單的例子說(shuō)明一下這個(gè)問(wèn)題所在。

看一段簡(jiǎn)單的代碼, 首先是錯(cuò)誤的示例:

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) // 直接打印結(jié)果})}for _, val := range slice {val()} } // 輸出 25 25 25 25 25

你可能會(huì)很奇怪為什么會(huì)出現(xiàn)這種情況,結(jié)果不應(yīng)該是1, 4, 9, 16, 25嗎?其實(shí)原因是循環(huán)變量的作用域的規(guī)則限制。在上面的程序中,v在 for 循環(huán)引進(jìn)的一個(gè)塊作用域內(nèi)進(jìn)行聲明。在循環(huán)里創(chuàng)建的所有函數(shù)變量共享相同的變量,就是一個(gè)可訪問(wèn)的存儲(chǔ)位置,而不是固定的值。(你會(huì)驚奇的發(fā)現(xiàn)&v的內(nèi)存地址是一樣的)

模擬一下實(shí)際的情況,假設(shè) v 變量的地址在 0x12345678 上, for 循環(huán)在迭代過(guò)程中,所有變量值都是在這地址上迭代的。當(dāng)最后調(diào)用匿名函數(shù)的時(shí)候,取值也是在這塊地址上。所以最后輸出的結(jié)果都是迭代的最后一個(gè)值。至少在 Go 語(yǔ)言中是不用質(zhì)疑的。這里也是一個(gè)陷阱,如果你不清楚的話(huà),肯定會(huì)遇到坑。那個(gè)該如何修改呢?

var slice []func()func main() {sli := []int{1, 2, 3, 4, 5}for _, v := range sli {temp := v // 其實(shí)很簡(jiǎn)單 引入一個(gè)臨時(shí)局部變量就可以了,這樣就可以將每次的值存儲(chǔ)到該變量地址上fmt.Println(&temp) // 這里內(nèi)存地址是不同的slice = append(slice, func(){fmt.Println(temp * temp) // 直接打印結(jié)果})}for _, val := range slice {val()} } // 輸出 1, 4, 9, 16, 25 預(yù)期結(jié)果

只需要引入一個(gè)局部變量便可以解決了,這是必須的。否則你的程序?qū)⒉粫?huì)有可預(yù)期的結(jié)果

總結(jié)

以上是生活随笔為你收集整理的for 循环迭代变量的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。