<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          快看! Go 1.22 對for循環(huán)進(jìn)行了兩個(gè)大更新

          共 4730字,需瀏覽 10分鐘

           ·

          2024-04-11 11:30

          前言

          Go 1.22 版本于 2024 年 2 月 6 日正式向世界宣告了版本的發(fā)布 。

          我們可以從官網(wǎng)下載1.22版本進(jìn)行體驗(yàn),或者從 Go Playground上進(jìn)行體驗(yàn)最新語法

          8dd1c510c96e36bbb8d294b367012de3.webp

          值得注意的是在語言層面上,這個(gè)版本對 for 循環(huán)進(jìn)行了兩處更新:

          • ? for循環(huán)的每次迭代都會(huì)定義新變量,而不再是共享一個(gè)變量

          • ? 支持對整數(shù)范圍進(jìn)行循環(huán)迭代

          今天將以案例的方式對比下最新版本 for 循環(huán)的兩個(gè)更新點(diǎn)。

          ?? Let's Go!

          循環(huán)不再共享循環(huán)變量

          ?? for在循環(huán)語義層面的坑

          Go1.22之前版本for 循環(huán)聲明的變量只創(chuàng)建一次,并在每次迭代中進(jìn)行更新,這會(huì)導(dǎo)致遍歷時(shí)訪問value時(shí)實(shí)際上都是訪問的同一個(gè)地址的值。

          相信不少小伙伴都遇到過,特別是在初學(xué)Go的時(shí)候!

          Go1.22之前版本

          我們用官博文章中那個(gè)例子,稍微改進(jìn)如下,并使用1.21版本運(yùn)行

              
              
                package main

          import "fmt"

          func main() {
              done := make(chan bool)

              values := []string{"xiao", "xu", "code"}
              for _, v := range values {
                  go func() {
                      fmt.Println(v)
                      done <- true
                  }()
              }

              // 等待所有的 goroutine 執(zhí)行結(jié)束
              for _ = range values {
                  <-done
              }
          }

          上述代碼運(yùn)行結(jié)果如下所示:

              
              
                code
          code
          code

          這三個(gè)創(chuàng)建的 goroutine 都在打印同一個(gè)變量 v,所以它們通常會(huì)打印出 "code"、"code"、"code",而不是以某種順序打印出 "xiao"、"xu" 和 "code"。

          ?? 這就是共享循環(huán)變量造成的問題!

          這個(gè)比較好理解,這個(gè)循環(huán)的 v 只創(chuàng)建一次,在每次循環(huán)的時(shí)候都會(huì)更新,而 閉包在訪問 v 時(shí)實(shí)際上都訪問的是同一個(gè)內(nèi)存地址,所以最終打印的都是同一個(gè)值。

          解決辦法:

          在Go版本不變的情況下,可以通過下面兩種方式修改代碼避免這個(gè)問題。

          1:將for循環(huán)中傳入v,代碼改造如下

              
              
                values := []string{"xiao", "xu", "code"}
          for _, v := range values {
              go func(v string) {
                  fmt.Println( v)
                  done <- true
              }(v)
          }

          2:在循環(huán)中重新定義一個(gè)變量進(jìn)行再次賦值

              
              
                values := []string{"xiao", "xu", "code"}
          for _, v := range values {
              value := v
              go func() {
                  fmt.Println( value)
                  done <- true
              }()
          }

          Go1.22版本

          不過這個(gè)問題在1.22版本已經(jīng)得到處理了,大家用這個(gè)版本的時(shí)候可以放心使用了,太爽了吧!

          我們在1.22版本上運(yùn)行和1.21一樣的代碼

              
              
                package main

          import "fmt"

          func main() {
              done := make(chan bool)

              values := []string{"xiao", "xu", "code"}
              for _, v := range values {
                  go func() {
                      fmt.Println(v)
                      done <- true
                  }()
              }

              // 等待所有的 goroutine 執(zhí)行結(jié)束
              for _ = range values {
                  <-done
              }
          }

          上述代碼運(yùn)行結(jié)果如下所示:

              
              
                code
          xiao
          xu

          for 循環(huán)的每次迭代都會(huì)創(chuàng)建新變量,每次循環(huán)迭代各自的變量,以避免意外共享錯(cuò)誤。上面一模一樣的代碼,輸出結(jié)果不再是固定的 code。

          支持整數(shù)范圍進(jìn)行循環(huán)迭代

          在 Go 1.22 版本之前, for range 僅支持對 array or slice、string、map 和 channel 類型的進(jìn)行迭代。

          而自 Go 1.22 版本起,新增了整數(shù)類型的迭代支持,我們能夠直接使用整數(shù)進(jìn)行循環(huán)迭代。

          下面同樣列舉不同版本的例子,看看差異性!

          Go1.22之前版本

              
              
                package main

          import "fmt"

          func main() {
              for i := range 5 {
                  fmt.Println("小許code", i)
              }
          }

          不支持遍歷整數(shù)范圍,這個(gè)range 5就直接提示報(bào)錯(cuò)了,編譯當(dāng)然有問題了

              
              
                .\main.go:15:17: cannot range over 5 (untyped int constant)
              
            

          Go1.22版本

              
              
                package main

          import "fmt"

          func main() {
              for i := range 5 {
                  fmt.Println("小許code", i)
              }
          }

          上述代碼運(yùn)行結(jié)果如下所示:

              
                小許code 0
          小許code 1
          小許code 2
          小許code 3
          小許code 4

          今天關(guān)于Go 1.22關(guān)于for循環(huán)的更新就介紹到這了,是不是覺得這個(gè)更新太棒啦!

          注意了,面試的同學(xué),如果沒有指定說明版本的話,還是需要注意下調(diào)整回之前的答案!



          推薦閱讀


          福利
          我為大家整理了一份 從入門到進(jìn)階的Go學(xué)習(xí)資料禮包 ,包含學(xué)習(xí)建議:入門看什么,進(jìn)階看什么。 關(guān)注公眾號 「polarisxu」,回復(fù)  ebook  獲?。贿€可以回復(fù)「進(jìn)群」,和數(shù)萬 Gopher 交流學(xué)習(xí)。

          瀏覽 57
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  高清拍少妇逼 | 日本熟妇在线 | 亚洲天堂视频一区 | 99操免费视频 | 婷婷成人免费视频 |