非阻塞 readline 挂起时泄漏 goroutine

Leaking goroutine when a non-blocking readline hangs

假设您有这样的结构:

ch := make(chan string)
errCh := make(chan error)
go func() {
    line, _, err := bufio.NewReader(r).ReadLine()
    if err != nil {
        errCh <- err
    } else {
        ch <- string(line)
    }
}()
select {
case err := <-errCh:
    return "", err
case line := <-ch:
    return line, nil
case <-time.After(5 * time.Second):
    return "", TimeoutError
}

在 5 秒超时的情况下,goroutine 挂起直到 ReadLine returns,这可能永远不会发生。我的项目是一个 long-运行 服务器,所以我不想堆积卡住的 goroutines。

ReadLine 不会 return 直到进程退出或方法读取一行。管道没有截止日期或超时机制。

如果在超时后 returns 调用 ReadLine,goroutine 将阻塞。这可以通过使用缓冲通道来解决:

ch := make(chan string, 1)
errCh := make(chan error, 1)

应用程序应调用 Wait 来清理与命令关联的资源。 goroutine 是调用它的好地方:

go func() {
  line, _, err := bufio.NewReader(r).ReadLine()
  if err != nil {
    errCh <- err
  } else {
    ch <- string(line)
  }
  cmd.Wait() // <-- add this line
}()

这将导致 goroutine 阻塞,而这正是您要避免的事情。替代方案是应用程序泄漏每个命令的资源。