测试我的代码不等待的 Goroutine

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

Testing Goroutine That My Code Does Not Wait For

问题

我有一个并发执行的函数。它的任务是运行一个命令行方法,并在出现错误时记录错误日志。我的主线程不等待这个方法执行完毕,而是乐观地返回。

如何测试我的函数?假设我给它一个cmdStr,比如{"sleep", "1"},它可以工作但不会立即返回,我该如何让我的测试等待这个函数执行完毕?

我希望确保实际运行这个函数的程序不必等待它执行完毕。

  1. func runCmd(cmdStr []string, errChan chan error) {
  2. cmd := exec.Command(cmdStr...)
  3. var out bytes.Buffer
  4. cmd.Stdout = &out
  5. err := cmd.Start()
  6. if err != nil {
  7. errChan <- err
  8. return
  9. }
  10. // 命令成功启动,所以我们的调用者可以继续执行。
  11. errChan <- nil
  12. err = cmd.Wait()
  13. if err != nil {
  14. log.Println(err)
  15. }
  16. }
英文:

I have a function that is executed concurrently. It's task is to run a command line method, logging an error if there is one. My main thread of execution does not wait for this method to finish. It simply returns optimistically.

How do I test my function? Assuming that I give it a cmdStr, such as {&quot;sleep&quot;, &quot;1&quot;}, that works but doesn't return instantly, how can I get my test to wait for this function to finish?

I want to ensure that the actual program that runs this does not have to wait for it to finish.

  1. func runCmd(cmdStr []string, errChan chan error) {
  2. cmd := exec.Command(cmdStr...)
  3. var out bytes.Buffer
  4. cmd.Stdout = &amp;out
  5. err := cmd.Start()
  6. if err != nil {
  7. errChan &lt;- err
  8. return
  9. }
  10. // Command started successfully, so our caller can continue.
  11. errChan &lt;- nil
  12. err = cmd.Wait()
  13. if err != nil {
  14. log.Println(err)
  15. }
  16. }

答案1

得分: 1

使用等待组(wait group)

  1. wg := sync.WaitGroup{}
  2. errc := make(chan error)
  3. wg.Add(1)
  4. go func() {
  5. runCmd([]string{"sleep", "1"}, errc)
  6. wg.Done()
  7. }()
  8. err := <-errc
  9. if err != nil {
  10. // 处理错误
  11. }
  12. wg.Wait()

请注意,以上是给出的代码的翻译版本。如果您有任何问题或需要进一步的帮助,请随时告诉我。

英文:

Use a wait group

  1. wg := sync.WaitGroup{}
  2. errc := make(chan error)
  3. wg.Add(1)
  4. go func() {
  5. runCmd([]string{&quot;sleep&quot;, 1}, errc)
  6. wg.Done()
  7. }()
  8. err &lt;- errc
  9. if err != nil {
  10. // handle error
  11. }
  12. wg.Wait()

答案2

得分: 0

最简单的方法是在main.main()的最后一条语句中添加select{}。但是这样main()将永远不会返回,你需要显式地终止进程。

另外一种更温和的方法是使用runtime.Gosched()等待其他goroutine,但它不能提供如此强的保证。

而规范的做法是:

  1. wg := sync.WaitGroup
  2. ...
  3. wg.Add(1)
  4. go runCmd(...)
  5. ...
  6. wg.Wait()
英文:

Simplest method to aware all goroutings done is to add select{} as last main.main() statement. But main() will never return this way and you should kill process explicitly.
It's also more gentle runtime.Goshed() to wait for others, but it can't provide such a strong guarantee.
And the canonical way would be

  1. wg := sync.WaitGroup
  2. ...
  3. wg.Add(1)
  4. go runCmd(...)
  5. ...
  6. wg.Wait()

huangapple
  • 本文由 发表于 2015年1月22日 23:07:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/28092062.html
匿名

发表评论

匿名网友

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

确定