测试我的代码不等待的 Goroutine

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

Testing Goroutine That My Code Does Not Wait For

问题

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

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

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

func runCmd(cmdStr []string, errChan chan error) {
  cmd := exec.Command(cmdStr...)
  var out bytes.Buffer
  cmd.Stdout = &out
  err := cmd.Start()
  if err != nil {
    errChan <- err
    return
  }
  // 命令成功启动,所以我们的调用者可以继续执行。
  errChan <- nil
  err = cmd.Wait()
  if err != nil {
    log.Println(err)
  }
}
英文:

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.

func runCmd(cmdStr []string, errChan chan error) {
  cmd := exec.Command(cmdStr...)
  var out bytes.Buffer
  cmd.Stdout = &amp;out
  err := cmd.Start()
  if err != nil {
    errChan &lt;- err
    return
  }
  // Command started successfully, so our caller can continue.
  errChan &lt;- nil
  err = cmd.Wait()
  if err != nil {
    log.Println(err)
  }
}

答案1

得分: 1

使用等待组(wait group)

wg := sync.WaitGroup{}
errc := make(chan error)
wg.Add(1)
go func() {
    runCmd([]string{"sleep", "1"}, errc)
    wg.Done()
}()
err := <-errc
if err != nil {
    // 处理错误
}
wg.Wait()

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

英文:

Use a wait group

wg := sync.WaitGroup{}
errc := make(chan error)
wg.Add(1)
go func() {
    runCmd([]string{&quot;sleep&quot;, 1}, errc)
    wg.Done()
}()
err &lt;- errc
if err != nil {
    // handle error
}
wg.Wait()

答案2

得分: 0

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

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

而规范的做法是:

wg := sync.WaitGroup
...
wg.Add(1)
go runCmd(...)
...
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

wg := sync.WaitGroup
...
wg.Add(1)
go runCmd(...)
...
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:

确定