对于某些背景,我对 Go 很陌生,但是在工作中编写这个程序的人离开了,所以现在代码是我的责任。该程序包装了一个 CLI 工具,用于写入 stdout 和 stderr。我们希望在处理输出的同时优雅地处理底层工具的错误。这是当前正在使用的相关代码片段: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()有谁知道为什么会发生最初的问题以及为什么交换两个扫描仪可以解决问题?我的猜测是两个扫描仪共享相同的底层缓冲区,这可能会导致一些问题,但我创建了两个不同的缓冲区并将它们分配给扫描仪,但并没有解决问题。任何帮助表示赞赏!
1 回答
心有法竹
TA贡献1866条经验 获得超5个赞
它的编写方式是,您的程序将等待直到从其中一个流中读取所有数据,具体取决于顺序。如果在从该流读取时,第二个流缓冲区已填满,则正在运行的程序(您正在读取其输出的程序)将阻塞,因为它无法再向该流写入任何输出。
看起来您并没有真正处理错误,因此您可以在 goroutine 中读取错误流:
go () {
for errScanner.Scan() {
...
}
}()
for scanner.Scan() {
...
}
- 1 回答
- 0 关注
- 182 浏览
添加回答
举报
0/150
提交
取消
