2017-10-12 57 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(...)使程序按预期的方式工作真的很黑客......)