Go 使用多个扫描仪时scanner.Scan()的顺序出现问题
对于某些背景来说,我是一个新手,但是在工作中编写这个程序的人离开了,所以代码现在是我的责任。此程序包装了一个CLI工具,该工具可写入stdout和stderr。我们希望在处理输出的同时,优雅地处理底层工具的错误 这是当前正在使用的相关代码片段:Go 使用多个扫描仪时scanner.Scan()的顺序出现问题,go,buffer,Go,Buffer,对于某些背景来说,我是一个新手,但是在工作中编写这个程序的人离开了,所以代码现在是我的责任。此程序包装了一个CLI工具,该工具可写入stdout和stderr。我们希望在处理输出的同时,优雅地处理底层工具的错误 这是当前正在使用的相关代码片段: cmd := exec.Command(args[0], args[1:]...) stdout, err := cmd.StdoutPipe() if err != nil { log.Fatal(err) } stderr, er
cmd := exec.Command(args[0], args[1:]...)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.Fatal(err)
}
cmd.Start()
scanner := bufio.NewScanner(stdout)
errScanner := bufio.NewScanner(stderr)
for errScanner.Scan() {
err := errScanner.Text()
log.Fatal(err)
}
for scanner.Scan() {
// proccess stdout data
}
if scanner.Err() != nil {
log.Fatal(scanner.Err())
}
cmd.Wait()
通常情况下,这很好。但是,如果写入标准输出的数据大小超过了64 KB的buf.MaxScanTokenSize,则程序将挂起,没有错误。底层命令完成,但两个循环的扫描器都未命中。我发现如果我交换errScanner.Scan()和scanner.Scan()的位置,那么问题就不再发生。这就是我的意思:
cmd := exec.Command(args[0], args[1:]...)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.Fatal(err)
}
cmd.Start()
scanner := bufio.NewScanner(stdout)
errScanner := bufio.NewScanner(stderr)
for scanner.Scan() {
// proccess stdout
}
for errScanner.Scan() {
err := errScanner.Text()
log.Fatal(err)
}
if scanner.Err() != nil {
log.Fatal(scanner.Err())
}
cmd.Wait()
有人知道为什么会出现最初的问题,以及为什么更换两个扫描仪可以解决这个问题吗?我的猜测是,两个扫描仪共享相同的底层缓冲区,这可能会导致一些问题,但我创建了两个不同的缓冲区,并将它们分配给扫描仪,但这并没有解决问题
感谢您的帮助 按照编写方式,您的程序将等待从其中一个流中读取所有数据,具体取决于顺序。如果在从该流读取时,第二个流缓冲区填满,则正在运行的程序(您正在读取其输出的程序)将阻塞,因为它无法向该流写入更多输出 看起来您并没有真正处理错误,因此您可以在goroutine中读取错误流:
go () {
for errScanner.Scan() {
...
}
}()
for scanner.Scan() {
...
}
好的,这是有道理的,并且澄清了我的很多问题。谢谢