我有代码,它以正确的方式工作,但它不是线程安全的 https://play.golang.org/p/8EY3i1Uk_aO在这些行中,比赛发生在这里。
stdout := cmd.Stdout.(*bytes.Buffer).String()
stderr := cmd.Stderr.(*bytes.Buffer).String()
我是这样重写的
readout, _ := cmd.StdoutPipe()
readerr, _ := cmd.StderrPipe()
链接 https://play.golang.org/p/htbn2zXXeQk
我不喜欢这里使用 MultiReader
并且我无法将数据 stdout 与 stderr 分开
r, _ := bufio.NewReader(io.MultiReader(readout, readerr)).ReadString('\n')
第二个例子也不起作用(在代码中有注释)。我希望 stdout 不会为空(就像这里的 https://play.golang.org/p/8EY3i1Uk_aO )
如何使逻辑像第一个例子一样,但它应该是线程安全的?
最佳答案
您必须在单独的 goroutine 中泵送 cmd.Stdout
和 cmd.Stderr
直到它们关闭,例如,就像您对 cmd.Stdin< 所做的那样
(但当然是在其他方向)。否则会有死锁的风险 - 进程被阻塞等待写入 stdout/stderr,并且您的程序被阻塞等待进程完成。
或者,如@JimB 所说,只需将字符串缓冲区分配给 cmd.Stdout
和 cmd.Stderr
,它们将在进程运行时被填充。
func invoke(cmd *exec.Cmd) (stdout string, stderr string, err error) {
stdoutbuf, stderrbuf := new(strings.Builder), new(strings.Builder)
cmd.Stdout = stdoutbuf
cmd.Stderr = stderrbuf
err = cmd.Start()
if err != nil {
return
}
err = cmd.Wait()
return stdoutbuf.String(), stderrbuf.String(), err
}
现场演示:
关于go - 使用 Stdout 和 Stderr 的线程安全操作(exec.Cmd),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68116457/