對于某些背景,我對 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 關注
- 121 瀏覽
添加回答
舉報
0/150
提交
取消