当所有 goroutine 完成时退出程序。

huangapple go评论79阅读模式
英文:

exit program when all goroutines finish

问题

我有两个Go协程函数,一个用于创建数据,另一个用于将数据添加到数据库中。当我完成创建数据后,我希望完成添加数据,但我不知道要调用该函数多少次。

for {
  select {
  case c <- dataChan:
    go func() {
      if data == false {
        return // 保持程序运行但永远不退出
      }
      createData(c.Data) // 将数据发送到dataChan,直到data == false
    }
    go func() {
      addData(c.Data) // 需要保持程序运行,直到所有这些goroutine完成
    }
  }
}

createData()函数创建并将数据发送到dataChan,根据一些变量,它最终会将data设置为false,并通过不断返回来保持程序持续运行,停止创建更多数据。但是,我觉得应该有一种更简洁的方法,允许我在所有addData()协程完成时退出。我看到有人使用通道来实现这一点,但我不知道要调用该函数多少次。

更新:可行的代码

var wg sync.WaitGroup
for {
  select {
  case c <- dataChan:
    wg.Add(1)
    go func() {
      if data == false {
        wg.Wait()
        os.Exit(0)
      }
      createData(c.Data)
    }
    go func() {
      addData(c.Data)
      defer wg.Done()
    }
  }
}

这段代码使用了sync.WaitGroup来等待所有的addData()协程完成。当datafalse时,它会等待所有协程完成后调用os.Exit(0)来退出程序。

英文:

I have two go routine functions, one creates data and one adds the data to the database. When I'm done creating data I want to finish adding data but I don't know how many times I'm going to call the function.

for {
  select {
  case c &lt;- dataChan:
    go func() {
      if data == false {
        return // keeps the program running but never exits
      }
      createData(c.Data) // sends data to dataChan until data == false 
    }
    go func() {
      addData(c.Data) // need to keep the program running until all these goroutines finish
    }
  }
}

createData() creates and sends data to the dataChan and based on some variables it will eventually set data to false and cause the program to be held open by returning over and over again and stops creating more data, but I feel like there should be a cleaner way that allows me to exit when all the addData() goroutines finish. I have seen people use a channel for this but I don't know exactly how many times I'm going to call the function.

UPDATE: WORKING CODE

var wg sync.WaitGroup
for {
  select {
  case c &lt;- dataChan:
    wg.Add(1)
    go func() {
      if data == false {
        wg.Wait()
        os.Exit(0)
      }
      createData(c.Data)
    }
    go func() {
      addData(c.Data)
      defer wg.Done()
    }
  }
}

答案1

得分: 6

sync.WaitGroup 是你在这里想要的。在每个 goroutine 开始之前使用 wg.Add(1)(或者如果你事先知道数量,可以使用 wg.Add(n)),在每个例程中使用 wg.Done() 表示完成,然后在 main 函数中使用 wg.Wait() 等待所有例程完成。链接的文档中有一个示例,并且正如文档中所指出的那样,直接复制示例代码可能不会达到你的目的;你可能需要将变量声明为指针(wg := new(sync.WaitGroup))。

英文:

sync.WaitGroup is what you want here. You wg.Add(1) before starting each goroutine (or wg.Add(n) if you know the count up front), wg.Done() in each routine when finished, and wg.Wait() in main to wait untill all finish. The linked docs have an example, and as the docs note, copying it won't do what you want; you may want to make the variable a pointer (wg := new(sync.WaitGroup)).

huangapple
  • 本文由 发表于 2017年8月18日 11:02:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/45747849.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定