为了账号安全,请及时绑定邮箱和手机立即绑定

使用多个扫描仪时,scanner.Scan() 的顺序问题

使用多个扫描仪时,scanner.Scan() 的顺序问题

Go
Helenr 2022-06-01 16:22:36
对于某些背景,我对 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() {

  ...

}


查看完整回答
反对 回复 2022-06-01
  • 1 回答
  • 0 关注
  • 182 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号