2017-10-12 58 views
1

WaitGroup夠程,我從博客https://nathanleclaire.com/blog/2014/02/15/how-to-wait-for-all-goroutines-to-finish-executing-before-continuing/與渠道

學習WaitGroup代碼:

package main 

import (
    "fmt" 
    "sync" 
    "time" 
) 

func main() { 
    messages := make(chan int) 
    var wg sync.WaitGroup 

    // you can also add these one at 
    // a time if you need to 

    wg.Add(3) 
    go func() { 
     defer wg.Done() 
     time.Sleep(time.Second * 3) 
     messages <- 1 
    }() 
    go func() { 
     defer wg.Done() 
     time.Sleep(time.Second * 2) 
     messages <- 2 
    }() 
    go func() { 
     defer wg.Done() 
     time.Sleep(time.Second * 1) 
     messages <- 3 
    }() 
    go func() { 
     for i := range messages { 
      fmt.Println(i) 
     } 
    }() 

    wg.Wait() 
} 

我認爲應該以打印3,2和1。但它只打印3,2,但1丟失,問題是什麼?

您可以樹它https://play.golang.org/p/kZCvDhykYM

回答

3

右鍵最新messages <- 1後,將推遲wg.Done()調用它在程序結束並釋放wg.Wait()和程序退出。當一個程序退出時,所有的goroutines都會死亡,所以打印goroutine沒有機會打印最新的值。

如果你在wg.Done()之後加上time.Sleep(time.Second * 1)之類的東西,你可以看到所有的輸出行。

+1

或者,使它成爲'wg.Add(4)',並在打印例程中放置一個'wg.Done()'作爲好。也就是說,我個人更喜歡把'wg.Wait()'放在goroutine中,並使用通道閉包作爲「完成」信號:https://play.golang.org/p/o-EYS_fK2k – Kaedys

0

所提到的博客開始於以下評論:

編輯:由於在this reddit的評論所指出的effenn,很多在這篇文章中的信息是「不準確的危險」。 OOPS!我已經爲您的觀看樂趣寫了一篇後續/更正文章here,但我將本文留作「歷史用途」。

Reddit commentfollowup article都描述了問題並給出瞭解決問題的方法。 (添加time.Sleep(...)使程序按預期的方式工作真的很黑客......)