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

Go for 循環(huán)有時(shí)候真的很坑。。。

開發(fā) 前端
如果實(shí)施,本次變更會(huì)導(dǎo)致 Go 的前后版本語(yǔ)義有所不同。還不如變成一個(gè) go.mod 文件的一個(gè)語(yǔ)義開關(guān),一變?nèi)儯駝t這種變一些不變一些的,會(huì)給問題排查和理解上帶來(lái)不少的成本。

大家好,我是煎魚。

不知道有多少 Go 的面試題和泄露,都和 for 循環(huán)有關(guān)。今天我在周末認(rèn)真一看,發(fā)現(xiàn)了 redefining for loop variable semantics[1] ,看來(lái)大家踩到的坑都是一樣的。

著名的硬核大佬 Russ Cox 表示他一直在研究這個(gè)問題,表示十年的經(jīng)驗(yàn)表明了當(dāng)前語(yǔ)義的代價(jià)是很大的,得動(dòng)一動(dòng),看看能不能打破兼容性原則。

想了下之前 Go modules 的事情,我真怕他一口氣就把這塔給推了...

問題

案例一

在 Go 語(yǔ)言中,我們寫 for 語(yǔ)句時(shí)有時(shí)會(huì)出現(xiàn)運(yùn)行和猜想的結(jié)果不一致。例如以下第一個(gè)案例的代碼:

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

這段代碼有問題嗎?變量 all 內(nèi)的 item 變量,存儲(chǔ)進(jìn)去的是什么?是每次循環(huán)的 item 值,每次都不一樣,對(duì)嗎?

實(shí)際上在 for 循環(huán)時(shí),每次存入變量 all 的都是相同的 item,也就是最后一個(gè)循環(huán)的 item 值。這是 Go 面試?yán)锝?jīng)常出現(xiàn)的題目,結(jié)合 goroutine 更風(fēng)騷,畢竟還會(huì)存在亂序執(zhí)行等問題。

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

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

要重新聲明一個(gè)局部變量 item 變量,把 for 循環(huán)的 item 變量給存儲(chǔ)下來(lái),再追加進(jìn)去。

案例二

接下來(lái)是第二個(gè)案例的代碼:

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

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

結(jié)果程序一運(yùn)行,輸出結(jié)果是 3,3,3。這又是為什么?

問題的重點(diǎn)之一:關(guān)注到閉包函數(shù),實(shí)際上所有閉包都打印的是相同的 v,也就是輸出 3,原因是在 for 循環(huán)結(jié)束后,最后 v 的值被設(shè)置為了 3,僅此而已。

如果想要達(dá)到預(yù)期的效果,依然是使用萬(wàn)能的再賦值。改寫后的代碼如下:

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

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

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

解決方案

修復(fù)思路

實(shí)際上 Go 核心團(tuán)隊(duì)在內(nèi)部和社區(qū)已經(jīng)討論過許久,希望重新定義 for 循環(huán)的語(yǔ)義。要達(dá)到的目的是:使循環(huán)變量每次迭代而不是每次循環(huán)。

解決的辦法是:在每個(gè)迭代變量 x 的每個(gè)循環(huán)體開頭,加一個(gè)隱式的再賦值,也就是 x := x,就能夠解決上述程序中所隱含的坑。

和我們現(xiàn)在做的一樣,只不過我們是自己手動(dòng)加的,Go 團(tuán)隊(duì)做的是希望在編譯器內(nèi)隱式處理。

讓用戶自己決定

比較尷尬的是 Go 團(tuán)隊(duì)在 Proposal: Go 2 transition[2] 中明確禁止重新定義語(yǔ)言的語(yǔ)義,所以 rsc 不能直接這么干。

因此 rsc 打算開個(gè)新坑,希望將會(huì)由用戶自己決定控制這個(gè) “破壞”,方式將會(huì)是根據(jù)每個(gè) modules 的 go.mod 文件中的 go 行(版本聲明)來(lái)決定語(yǔ)義。

例如,如果是在 Go1.30 對(duì)本文討論的 for 循環(huán)將循環(huán)變量改為迭代,那么在 go.mod 文件中的 go 版本聲明是將是一個(gè)關(guān)鍵的開關(guān)。

如下圖示:

圖片

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

如此一來(lái)上述提到的 for 循環(huán)問題都會(huì)在一定范圍內(nèi)被解決。

總結(jié)

for 循環(huán)時(shí)的變量問題,一直是各大 Go 考官愛考的題目,也確實(shí)在實(shí)際編程 Go 代碼時(shí)會(huì)遇到這類坑。

雖然 rsc 希望在 go.mod 文件上開創(chuàng)先河,利用 go 版本的聲明,去修改語(yǔ)義(不允許添加和刪除)。這無(wú)疑是給 Go1 兼容性保障開了一個(gè)后門。

如果實(shí)施,本次變更會(huì)導(dǎo)致 Go 的前后版本語(yǔ)義有所不同。還不如變成一個(gè) go.mod 文件的一個(gè)語(yǔ)義開關(guān),一變?nèi)儯駝t這種變一些不變一些的,會(huì)給問題排查和理解上帶來(lái)不少的成本。

這顯然是一個(gè)很折騰人的思考題。

責(zé)任編輯:武曉燕 來(lái)源: 腦子進(jìn)煎魚了
相關(guān)推薦

2019-11-05 09:20:06

SQLiteLinux

2018-10-30 12:44:04

Linux系統(tǒng)內(nèi)存

2013-04-08 15:39:15

程序員

2010-02-23 16:21:24

Python Win

2010-01-20 10:14:53

C++程序

2013-12-11 09:29:02

2019-12-06 17:31:30

程序員人生第一份工作設(shè)計(jì)

2014-10-24 10:10:33

UbuntuUbuntu 14.1

2010-03-17 14:50:06

智能交換機(jī)

2010-03-10 11:14:56

智能交換機(jī)

2025-05-28 01:10:00

SQL索引MySQL

2009-09-28 11:20:30

面試

2010-08-30 10:37:04

云計(jì)算

2025-05-28 00:00:00

CSS前端Flexbox

2010-03-10 16:51:21

以太網(wǎng)交換機(jī)

2019-01-21 13:56:52

2021-08-14 08:10:58

物聯(lián)網(wǎng)IOT

2023-05-22 07:10:38

GPTpromptPerplexity

2022-11-15 11:13:10

域名Linux文件

2016-11-15 09:43:56

大數(shù)據(jù)數(shù)據(jù)工程師
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩免费三级 | 亚洲资源站 | 不卡一区 | 第四色影音先锋 | 日韩在线视频免费观看 | 天堂久久天堂综合色 | 免费三级网 | 日韩国产欧美视频 | 国产一区二区久久 | 亚洲有码转帖 | 免费精品在线视频 | 91精品麻豆日日躁夜夜躁 | 亚洲成人免费视频 | 自拍在线 | 久久久性色精品国产免费观看 | 天天干天天插天天 | 超碰精品在线观看 | av免费观看网站 | 国产精品一区二区av | 国产女人与拘做受视频 | 亚洲精品一区二区三区蜜桃久 | 久久久久国产精品一区二区 | 天天躁日日躁狠狠躁2018小说 | 天天天插 | 精品一区二区久久久久久久网精 | 色欧美综合 | 午夜免费福利片 | 亚洲国产成人久久综合一区,久久久国产99 | 在线视频 亚洲 | 四虎最新地址 | 黄色片免费看 | 在线观看国产视频 | 狠狠干网站 | 亚洲在线高清 | 免费一级片| 亚洲经典一区 | 精品一区二区三区在线观看 | 久久久人成影片一区二区三区 | 欧美成人精品一区二区三区 | 色天天综合 | 99精品网 |