成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go 團隊將修改 for 循環變量的語義,Go1.21 新版本即可體驗!

開發 前端
在本次 Go 新版本更新中,Go 官方核心團隊終于解決了這個十年之痛的問題。前面鋪墊了真的是非常久了,這么多年,為了兼容性還出臺了幾個兼容性提案。真的是用心良苦!

大家好,我是煎魚。

之前有提到 Go for 循環變量的問題,許多面試題和泄露與此有關。

Russ Cox(下稱:rsc)甚至一度表示他一直在研究這個問題,認為當前語義的代價是很大的,想看看能不能進行變更。

經過 Go1 向前兼容性和向后兼容性提案的鋪墊,循環變量的這個問題將得到解決。在 Go1.21 可以進行嘗試使用,預計 Go1.22 開始正式變更。

回顧問題現象

第一個例子

在 Go 語言中,我們寫 for 語句時有時會出現運行和猜想的結果不一致。例如以下第一個案例的代碼:

var all []*Item
for _, item := range items {
 all = append(all, &item)
}

這段代碼有問題嗎?變量 all 內的 item 變量,存儲進去的是什么?是每次循環的 item 值,每次都不一樣,對嗎?

實際上在 for 循環時,每次存入變量 all 的都是相同的 item,也就是最后一個循環的 item 值。這是 Go 面試里經常出現的題目,結合 goroutine 更風騷,畢竟還會存在亂序執行等問題。

如果你想解決這個問題,就需要把程序改寫成如下:

var all []*Item
for _, item := range items {
 item := item
 all = append(all, &item)
}

要重新聲明一個局部變量 item 變量,把 for 循環的 item 變量給存儲下來,再追加進去。

第二個例子

接下來是第二個案例的代碼:

var prints []func()
for _, v := range []int{1, 2, 3} {
 prints = append(prints, func() { fmt.Println(v) })
}
for _, print := range prints {
 print()
}

這段程序的輸出結果是什么?沒有 & 取地址符,是輸出 1,2,3 嗎?

結果程序一運行,輸出結果是 3,3,3。這又是為什么?

問題的重點之一:關注到閉包函數,實際上所有閉包都打印的是相同的 v,也就是輸出 3,原因是在 for 循環結束后,最后 v 的值被設置為了 3,僅此而已。

如果想要達到預期的效果,依然是使用萬能的再賦值。改寫后的代碼如下:

for _, v := range []int{1, 2, 3} {
  v := v
  prints = append(prints, func() { fmt.Println(v) })
 }

增加 v := v 語句,程序輸出結果為 1,2,3。仔細翻翻你寫過的 Go 工程,是不是都很熟悉?就這改造方法,贏了。

尤其是配合上 Goroutine 的寫法,很多同學會更容易在此翻車。

解決方案

GOEXPERIMENT=loopvar

在 Go1.21 的新版本起,我們可以開啟 GOEXPERIMENT=loopvar 來構建 Go 程序,來體驗上面提到的 for 循環變量的問題。

構建命令:

GOEXPERIMENT=loopvar go install my/program
GOEXPERIMENT=loopvar go build my/program
GOEXPERIMENT=loopvar go test my/program
GOEXPERIMENT=loopvar go test my/program -bench=.
...

預計在 Go1.22 起,新的 for 循環語義,將會在 go.mod 文件中的 go 行(版本聲明)大于等于 Go1.22 下默認應用。

我們對應到上述的第二個例子,程序的運行結果將發生如下改變:

$ go run demo.go                        
3
3
3
$ GOEXPERIMENT=loopvar gotip run demo.go
1
2
3

以后就不再需要寫 v := v 語句了。

模塊版本控制開關

go.mod 方面,具體可以參照以下案例:

圖片圖片

像上圖的配置,Go 1.30 或更高版本將會每次迭代變量(也就是新的 for 循環語義),而早期 Go 版本的將每次循環變量,也就是 go.mod 的 Go 版本控制了新特性的語義,不同 modules 都可能會因此不一樣。

如此一來上述提到的 for 循環問題都會在一定范圍(版本)內被解決。

查看影響范圍

可以在命令行執行以下指令進行構建:

$ go build -gcflags=all=-d=loopvar=2 cmd/go
...
modload/import.go:676:7: loop variable d now per-iteration, stack-allocated
modload/query.go:742:10: loop variable r now per-iteration, heap-allocated

我們就可以看到對應的文件、行數、變量。知道目前對應的是迭代還是循環,變量分配在哪里。不用靠再翻版本號再看再猜。

實際應用實驗

在 2023 年 5 月初起,Google 一直在內部使用 for 循環的新語義。截止目前為止,沒有報告任何新問題。

另外還在 Kubernetes 中嘗試了新的 Go1.21 版本和新的 for 循環語義測試:

圖片圖片

將 Kubernetes 從 Go 1.20 更新到 Go 1.21 時,發現了 3 個新失敗的測試。而 for 循環變量的語義更改,則造成了 2 個新的失敗。與普通版本更新相比,Go 官方團隊認為并不是一個重大的新負擔。

綜合認為這不是一個大變動,且影響面可以控制。所以可變!

總結

在本次 Go 新版本更新中,Go 官方核心團隊終于解決了這個十年之痛的問題。前面鋪墊了真的是非常久了,這么多年,為了兼容性還出臺了幾個兼容性提案。真的是用心良苦!

大家要關注一下自己的應用程序,可以在 Go1.21 提前把開關開起來,看看是否有影響。如果沒有影響,那就是最好的了。如果有影響,那么需要注意在后續升級新版本(Go1.22 時),要控制好 go.mod 中的 Go 版本信息。

在下個版本(Go1.21/Go1.22)起,Go 代碼的 v := v 語句將會逐漸變少。可能是個好事?

面試官們也請記得修改一下你的題庫了。

責任編輯:武曉燕 來源: 腦子進煎魚了
相關推薦

2023-06-19 08:49:55

go文件管理

2025-01-14 11:01:38

2023-08-09 08:53:50

GoWASI語義

2021-09-18 10:45:58

Windows 11Windows微軟

2023-08-02 08:46:02

Go版本號規則

2023-06-07 10:32:57

內置函數clear

2022-12-09 08:52:51

Go匿名接口

2025-05-06 00:00:08

2014-04-17 15:02:10

聯想“樂安全”智能手機

2023-06-29 08:47:59

GoContext設置

2023-05-09 11:02:22

Go內聯版本

2023-05-05 08:51:18

Go語言泛型

2011-07-18 10:24:18

Debian 7Hurd內核

2011-04-25 13:23:15

Windows PhoWindows Pho微軟

2021-07-25 09:18:04

QQ騰訊移動應用

2011-08-01 15:35:51

GlassFishJava 7

2013-03-28 15:59:34

為知筆記

2010-02-23 17:44:48

Python 3.0

2009-06-17 09:24:34

學習strutsStruts新版本

2013-12-10 16:00:46

金和移動OA
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美成人a∨高清免费观看 老司机午夜性大片 | 欧美mv日韩mv国产网站91进入 | 日日日干干干 | 在线国产小视频 | 成人黄页在线观看 | 日韩中文字幕在线不卡 | 日韩免费在线视频 | 蜜桃视频在线观看免费视频网站www | 午夜视频一区二区 | 中文字幕亚洲区一区二 | 99精品国自产在线观看 | 91麻豆精品国产91久久久更新资源速度超快 | 久久久久一区 | 国产精品一级 | 狠狠操狠狠色 | 99精品国自产在线 | 91久久 | 亚洲精品中文字幕 | 国产一区二区三区高清 | 亚洲精品国产第一综合99久久 | 国内精品视频免费观看 | 九九热在线免费视频 | 精品欧美激情精品一区 | 亚洲综合免费 | 日韩免费一区二区 | 国产精品久久久久久久7电影 | 国产福利视频导航 | 香蕉视频久久久 | 亚洲高清成人 | 国产精品无 | 欧美日在线| 婷婷久久综合 | 中文在线观看视频 | 成人免费网站视频 | 91看片网| 国产综合在线视频 | 欧美在线亚洲 | 亚洲日本视频 | 五月天激情综合网 | www.日本精品 | 欧美色图综合网 |