在某些背景下,我对Go还是很陌生,但是在工作中编写此程序的人离开了,所以代码现在是我的责任。该程序包装了一个可写入stdout和stderr的CLI工具。我们希望在处理输出的同时,还可以优雅地处理基础工具的错误。
这是当前正在使用的相关代码段:
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()
通常,这很好。但是,如果写入标准输出的数据大小超过buf.MaxScanTokenSize,即64 KB,则程序将挂起且没有错误。基本命令完成,但是没有扫描程序循环。我发现,如果交换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() {
...
}
关于go - 使用多个扫描仪时,scanner.Scan()的顺序出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61622786/