找代理做網(wǎng)站推廣靠譜嗎app推廣軟件
對(duì)goroutine和循環(huán)變量處理不當(dāng)可能是Go開(kāi)發(fā)人員在編寫(xiě)并發(fā)應(yīng)用程序時(shí)最常犯的錯(cuò)誤之一。讓我們看一個(gè)具體的例子,然后我們將定義發(fā)生此類(lèi)錯(cuò)誤的條件以及如何防止發(fā)生這類(lèi)錯(cuò)誤。
在下面的示例中,我們初始化一個(gè)切片,然后在作為新goroutine執(zhí)行的閉包中訪(fǎng)問(wèn)這個(gè)元素:
s := []int{1, 2, 3}for _, i := range s {go func() {fmt.Print(i)}()
}
我們可能會(huì)預(yù)期這段代碼不以特定的順序打印123(因?yàn)椴荒鼙WC創(chuàng)建的第一個(gè)goroutine會(huì)首先執(zhí)行完成)。這段代碼的輸出不是確定性的。例始,有時(shí)會(huì)打印233,有時(shí)會(huì)打印333。這是什么原因呢?
在這個(gè)例子中,我們從一個(gè)閉包創(chuàng)建新的goroutine。提醒一下,閉包是一個(gè)函數(shù)值,它從其主體外部引用變量:在這里就是變量i。我們必須知道,當(dāng)一個(gè)閉包goroutine被執(zhí)行時(shí),它不會(huì)捕獲goroutine創(chuàng)建時(shí)的值。而是,所有的goroutine都引用完全相同的變量。當(dāng)一個(gè)goroutine運(yùn)行時(shí),會(huì)在執(zhí)行fmt.Print時(shí)打印i的值。因此,自goroutine啟動(dòng)以來(lái),i 可能已被修改。
下圖顯示了代碼打印233時(shí)可能的執(zhí)行情況。隨著時(shí)間的推移,i的值會(huì)發(fā)生變化:1、2,然后是3。在每次迭代中,我們都會(huì)啟動(dòng)一個(gè)新的goroutine。因?yàn)闊o(wú)法何證每個(gè)goroutine何時(shí)啟動(dòng)和完成,所以結(jié)果也會(huì)有所不同。在這個(gè)例子中,當(dāng)i等于2時(shí),第一個(gè)goroutine打印i。當(dāng)i的值已經(jīng)等于3時(shí),其他gorout