最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于Golang中for-loop與goroutine的問(wèn)題詳解

 更新時(shí)間:2017年09月04日 08:43:24   作者:寇池濱  
這篇文章主要給大家介紹了關(guān)于Golang中for-loop與goroutine問(wèn)題的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用golang具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。

背景

最近在學(xué)習(xí)MIT的分布式課程6.824的過(guò)程中,使用Go實(shí)現(xiàn)Raft協(xié)議時(shí)遇到了一些問(wèn)題。分享出來(lái)供大家參考學(xué)習(xí),下面話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。

參見(jiàn)如下代碼:

for i := 0; i < len(rf.peers); i++ {
  DPrintf("i = %d", i)

  if i == rf.me {
   DPrintf("skipping myself #%d", rf.me)
   continue
  }

  go func() {
   DPrintf("len of rf.peers = %d", len(rf.peers))
   DPrintf("server #%d sending request vote to server %d", rf.me, i)
   reply := &RequestVoteReply{}
   ok := rf.sendRequestVote(i, args, reply)
   if ok && reply.VoteGranted && reply.Term == rf.currentTerm {
    rf.voteCount++
    if rf.voteCount > len(rf.peers)/2 {
     rf.winElectionCh <- true
    }
   }
  }()
}

其中,peers切片的長(zhǎng)度為3,因此最高下標(biāo)為2,在非并行編程中代碼中的for-loop應(yīng)該是很直觀的,我當(dāng)時(shí)并沒(méi)有意識(shí)到有什么問(wèn)題??墒窃谡{(diào)試過(guò)程中,一直在報(bào) index out of bounds 錯(cuò)誤。調(diào)試信息顯示i的值為3,當(dāng)時(shí)就一直想不明白循環(huán)條件明明是 i < 2,怎么會(huì)變成3呢。

分析

雖然不明白發(fā)生了什么,但知道應(yīng)該是循環(huán)中引入的 goroutine 導(dǎo)致的。經(jīng)過(guò)Google,發(fā)現(xiàn)Go的wiki中就有一個(gè)頁(yè)面 Common Mistake - Using goroutines on loop iterator variables 專門(mén)提到了這個(gè)問(wèn)題,看來(lái)真的是很 common 啊,笑哭~

初學(xué)者經(jīng)常會(huì)使用如下代碼來(lái)并行處理數(shù)據(jù):

for val := range values {
 go val.MyMethod()
}

或者使用閉包(closure):

for val := range values {
 go func() {
  fmt.Println(val)
 }()
}

這里的問(wèn)題在于 val 實(shí)際上是一個(gè)遍歷了切片中所有數(shù)據(jù)的單一變量。由于閉包只是綁定到這個(gè) val 變量上,因此極有可能上面的代碼的運(yùn)行結(jié)果是所有 goroutine 都輸出了切片的最后一個(gè)元素。這是因?yàn)楹苡锌赡墚?dāng) for-loop 執(zhí)行完之后 goroutine 才開(kāi)始執(zhí)行,這個(gè)時(shí)候 val 的值指向切片中最后一個(gè)元素。

The val variable in the above loops is actually a single variable that takes on the value of each slice element. Because the closures are all only bound to that one variable, there is a very good chance that when you run this code you will see the last element printed for every iteration instead of each value in sequence, because the goroutines will probably not begin executing until after the loop.

解決方法

以上代碼正確的寫(xiě)法為:

for val := range values {
 go func(val interface{}) {
  fmt.Println(val)
 }(val)
}

在這里將 val 作為一個(gè)參數(shù)傳入 goroutine 中,每個(gè) val 都會(huì)被獨(dú)立計(jì)算并保存到 goroutine 的棧中,從而得到預(yù)期的結(jié)果。

另一種方法是在循環(huán)內(nèi)定義新的變量,由于在循環(huán)內(nèi)定義的變量在循環(huán)遍歷的過(guò)程中是不共享的,因此也可以達(dá)到同樣的效果:

for i := range valslice {
 val := valslice[i]
 go func() {
  fmt.Println(val)
 }()
}

對(duì)于文章開(kāi)頭提到的那個(gè)問(wèn)題,最簡(jiǎn)單的解決方案就是在循環(huán)內(nèi)加一個(gè)臨時(shí)變量,并將后面 goroutine 內(nèi)的 i 都替換為這個(gè)臨時(shí)變量即可:

server := i

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • 一文搞懂Golang中的內(nèi)存逃逸

    一文搞懂Golang中的內(nèi)存逃逸

    內(nèi)存逃逸是 Go 語(yǔ)言中一個(gè)重要的概念,涉及到程序的性能優(yōu)化和內(nèi)存管理,了解內(nèi)存逃逸可以幫助我們編寫(xiě)更高效的代碼,本文將從基本概念入手,深入講解 Go 語(yǔ)言中的內(nèi)存逃逸現(xiàn)象,以及如何避免,需要的朋友可以參考下
    2023-12-12
  • go?字符串修改的操作代碼

    go?字符串修改的操作代碼

    這篇文章主要介紹了go?字符串修改,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • 一文帶你了解Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)strings的常用函數(shù)和方法

    一文帶你了解Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)strings的常用函數(shù)和方法

    strings?庫(kù)包含了許多高效的字符串常用操作的函數(shù)和方法,巧用這些函數(shù)與方法,能極大的提高我們程序的性能。本文就來(lái)和大家分享一下Go標(biāo)準(zhǔn)庫(kù)strings的常用函數(shù)和方法,希望對(duì)大家有所幫助
    2022-11-11
  • 一文幫你搞懂Go面試中常問(wèn)的channel問(wèn)題

    一文幫你搞懂Go面試中常問(wèn)的channel問(wèn)題

    channel是Golang面試時(shí)經(jīng)常會(huì)問(wèn)到的問(wèn)題,所以這篇文章為大家整理了channel常考的一些問(wèn)題以及回答,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-06-06
  • 淺談Go Channel 高級(jí)實(shí)踐

    淺談Go Channel 高級(jí)實(shí)踐

    這篇文章主要介紹了淺談Go Channel 高級(jí)實(shí)踐,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • Golang?rabbitMQ生產(chǎn)者消費(fèi)者實(shí)現(xiàn)示例

    Golang?rabbitMQ生產(chǎn)者消費(fèi)者實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了Golang?rabbitMQ生產(chǎn)者消費(fèi)者實(shí)現(xiàn)的示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • 基于golang中container/list包的用法說(shuō)明

    基于golang中container/list包的用法說(shuō)明

    這篇文章主要介紹了基于golang中container/list包的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • 詳解Go語(yǔ)言中的逃逸分析

    詳解Go語(yǔ)言中的逃逸分析

    逃逸分析是編譯器用于決定將變量分配到棧上還是堆上的一種行為,下面小編就來(lái)為大家詳細(xì)講講go語(yǔ)言中是如何進(jìn)行逃逸分析的,需要的小伙伴可以參考下
    2023-09-09
  • golang實(shí)現(xiàn)多協(xié)程下載文件(支持?jǐn)帱c(diǎn)續(xù)傳)

    golang實(shí)現(xiàn)多協(xié)程下載文件(支持?jǐn)帱c(diǎn)續(xù)傳)

    本文主要介紹了golang實(shí)現(xiàn)多協(xié)程下載文件,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Go如何實(shí)現(xiàn)HTTP請(qǐng)求限流示例

    Go如何實(shí)現(xiàn)HTTP請(qǐng)求限流示例

    本篇文章主要介紹了Go如何實(shí)現(xiàn)HTTP請(qǐng)求限流示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04

最新評(píng)論

丹东市| 宁安市| 新沂市| 平遥县| 大关县| 油尖旺区| 古丈县| 石嘴山市| 安乡县| 交口县| 宜兴市| 沂水县| 新巴尔虎左旗| 璧山县| 谢通门县| 商都县| 开鲁县| 梅河口市| 岱山县| 明溪县| 常山县| 饶河县| 赣榆县| 高碑店市| 孙吴县| 涞水县| 清徐县| 策勒县| 汝城县| 奉化市| 景东| 灯塔市| 叶城县| 赤壁市| 嘉荫县| 灵武市| 通渭县| 曲靖市| 射洪县| 南安市| 崇信县|