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

關于Golang中for-loop與goroutine的問題詳解

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

背景

最近在學習MIT的分布式課程6.824的過程中,使用Go實現Raft協議時遇到了一些問題。分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。

參見如下代碼:

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切片的長度為3,因此最高下標為2,在非并行編程中代碼中的for-loop應該是很直觀的,我當時并沒有意識到有什么問題??墒窃谡{試過程中,一直在報 index out of bounds 錯誤。調試信息顯示i的值為3,當時就一直想不明白循環(huán)條件明明是 i < 2,怎么會變成3呢。

分析

雖然不明白發(fā)生了什么,但知道應該是循環(huán)中引入的 goroutine 導致的。經過Google,發(fā)現Go的wiki中就有一個頁面 Common Mistake - Using goroutines on loop iterator variables 專門提到了這個問題,看來真的是很 common 啊,笑哭~

初學者經常會使用如下代碼來并行處理數據:

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

或者使用閉包(closure):

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

這里的問題在于 val 實際上是一個遍歷了切片中所有數據的單一變量。由于閉包只是綁定到這個 val 變量上,因此極有可能上面的代碼的運行結果是所有 goroutine 都輸出了切片的最后一個元素。這是因為很有可能當 for-loop 執(zhí)行完之后 goroutine 才開始執(zhí)行,這個時候 val 的值指向切片中最后一個元素。

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.

解決方法

以上代碼正確的寫法為:

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

在這里將 val 作為一個參數傳入 goroutine 中,每個 val 都會被獨立計算并保存到 goroutine 的棧中,從而得到預期的結果。

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

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

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

server := i

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關文章

  • 一文搞懂Golang中的內存逃逸

    一文搞懂Golang中的內存逃逸

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

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

    這篇文章主要介紹了go?字符串修改,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • 一文帶你了解Go語言標準庫strings的常用函數和方法

    一文帶你了解Go語言標準庫strings的常用函數和方法

    strings?庫包含了許多高效的字符串常用操作的函數和方法,巧用這些函數與方法,能極大的提高我們程序的性能。本文就來和大家分享一下Go標準庫strings的常用函數和方法,希望對大家有所幫助
    2022-11-11
  • 一文幫你搞懂Go面試中常問的channel問題

    一文幫你搞懂Go面試中常問的channel問題

    channel是Golang面試時經常會問到的問題,所以這篇文章為大家整理了channel??嫉囊恍﹩栴}以及回答,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-06-06
  • 淺談Go Channel 高級實踐

    淺談Go Channel 高級實踐

    這篇文章主要介紹了淺談Go Channel 高級實踐,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • Golang?rabbitMQ生產者消費者實現示例

    Golang?rabbitMQ生產者消費者實現示例

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

    基于golang中container/list包的用法說明

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

    詳解Go語言中的逃逸分析

    逃逸分析是編譯器用于決定將變量分配到棧上還是堆上的一種行為,下面小編就來為大家詳細講講go語言中是如何進行逃逸分析的,需要的小伙伴可以參考下
    2023-09-09
  • golang實現多協程下載文件(支持斷點續(xù)傳)

    golang實現多協程下載文件(支持斷點續(xù)傳)

    本文主要介紹了golang實現多協程下載文件,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Go如何實現HTTP請求限流示例

    Go如何實現HTTP請求限流示例

    本篇文章主要介紹了Go如何實現HTTP請求限流示例,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04

最新評論

景东| 景德镇市| 庆城县| 会理县| 灵丘县| 曲沃县| 汾西县| 手游| 高要市| 电白县| 富锦市| 通河县| 都兰县| 大余县| 铁力市| 中西区| 伽师县| 广饶县| 乌拉特后旗| 新宁县| 武川县| 龙山县| 黑河市| 蕉岭县| 鄯善县| 固镇县| 昌黎县| 衡山县| 略阳县| 连江县| 莫力| 宝清县| 雅江县| 运城市| 汉川市| 六枝特区| 阳新县| 重庆市| 北京市| 新巴尔虎右旗| 布尔津县|