GoRoutines,具有WaitGroup意外输出的频道

时间:2015-08-11 14:59:28

标签: go

我查看了很久以前写过的一些代码,当时go1.3发布了(我可能错了)。 CODE HERE

以下代码过去按预期工作,但现在我将go更新为当前主版本(go version devel + bd1efd5 Fri Jul 31 16:11:21 2015 +0000 darwin / amd64) ,最后一条输出消息c <- "FUNC 1 DONE"未打印,代码在play.golang.org上正常工作。我做错了什么,或者这是一个错误?

package main

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

func test(c chan string, wg *sync.WaitGroup) {
  defer wg.Done()
  fmt.Println("EXEC FUNC 1")
  time.Sleep(3 * time.Second)
  c <- "FUNC 1 DONE"
}

func test1(c chan string, wg *sync.WaitGroup) {
  defer wg.Done()
  fmt.Println("EXEC FUNC 2")
  time.Sleep(2 * time.Second)
  c <- "FUNC 2 DONE"
}

func main() {
  ch := make(chan string)

  var wg sync.WaitGroup
  wg.Add(2)

  go test(ch, &wg)
  go test1(ch, &wg)

  go func(c chan string) {
    for txt := range c {
      fmt.Println(txt)
    }
  }(ch)

  wg.Wait()
}

更新:

我不是说,上述是做这类工作的最佳方式,但我认为没有任何问题。

同样在go version go1.4.2 darwin/amd64中运行它将返回预期的输出。

1 个答案:

答案 0 :(得分:7)

您的代码一直有此错误。只有偶然的机会,您的程序才能在主要退出之前打印所有消息。

为了使这项工作正常,我会在wg.Wait()和频道接收的地方反转,这样你就可以异步关闭频道。这样接收操作就是阻塞main,并且一旦所有发送操作完成,通道就会关闭。

func main() {
    ch := make(chan string)

    var wg sync.WaitGroup
    wg.Add(2)

    go test(ch, &wg)
    go test1(ch, &wg)

    go func() {
        wg.Wait()
        close(ch)
    }()

    for txt := range ch {
        fmt.Println(txt)
    }
}