【发布时间】:2019-11-11 15:56:02
【问题描述】:
我正在尝试使用 Go 将 sqlite3 作为进程运行。我想将cmd.Stdin 与bytes.Buffer 和os.Stdin 结合起来。然而,当我在标准输入字节缓冲区上写.quit 命令时,程序并没有直接退出,而是在等待来自os.stdin 的换行符。当它收到来自os.stdin 的换行符时,它就退出了。
我尝试调用os.Stdin.Write([]byte("\n")),但没有成功。如何在.quit 命令之后直接退出而不与os.Stdin 进行任何交互?
func main() {
cmd := exec.Command("/usr/bin/sqlite3")
bufOut, bufErr, bufIn := &bytes.Buffer{}, &bytes.Buffer{}, &bytes.Buffer{}
cmd.Stdout = io.MultiWriter(bufOut, os.Stdout)
cmd.Stderr = io.MultiWriter(bufErr, os.Stderr)
cmd.Stdin = io.MultiReader(bufIn, os.Stdin)
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
// Execute .help command on sqlite3
if _, err := bufIn.Write([]byte(".help\n")); err != nil {
log.Fatal(err)
}
// Execute .quit command on sqlite3 (should exit here)
if _, err := bufIn.Write([]byte(".quit\n")); err != nil {
log.Fatal(err)
}
// Nevertheless, it requires a '\n' from os.Stdin before exiting
if err := cmd.Wait(); err != nil {
log.Fatal(err)
}
fmt.Println("out:", bufOut.String(), "err:", bufErr.String())
}
【问题讨论】:
-
bufIn上存在数据竞争。通过在调用cmd.Start()之前将命令写入bufIn来修复。鉴于程序试图在读取os.Stdin之前退出,读取表单os.Stdin的目的是什么? -
@CeriseLimón 这只是一个显示问题的示例。在
.quit命令之前应该可以从os.stdin或bufIn读取。顺便说一句,我在调用 cmd.Start() 之前测试过写信给bufIn但是我仍然有问题 -
发布的代码在发出
.quit命令后从 os.Stdin 读取。在执行bufIn和/或os.Stdin之后使用以下命令执行.quit命令:cmd.Stdin = io.MultiReader(bufIn, os.Stdin, srings.NewReader(".quit\n"))。由于命令在 EOF 上退出,因此无需使用.quit命令结束。无论如何,您都应该解决数据竞争问题。