1 回答

TA貢獻(xiàn)2016條經(jīng)驗(yàn) 獲得超9個(gè)贊
嘗試這樣的事情(下面的解釋):
package main
import (
? ? "fmt"
? ? "io"
? ? "io/ioutil"
? ? "log"
? ? "mime/multipart"
? ? "os"
? ? "os/exec"
? ? "sync"
? ? "github.com/pkg/errors"
)
func readCommand(cmdStdout io.ReadCloser, wg *sync.WaitGroup, resc chan<- []byte, errc chan<- error) {
? ? defer wg.Done()
? ? defer close(errc)
? ? defer close(resc)
? ? mr := multipart.NewReader(cmdStdout, "foo")
? ? for {
? ? ? ? part, err := mr.NextPart()
? ? ? ? if err != nil {
? ? ? ? ? ? if err == io.EOF {
? ? ? ? ? ? ? ? fmt.Println("EOF")
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? errc <- errors.Wrap(err, "failed to get next part")
? ? ? ? ? ? }
? ? ? ? ? ? return
? ? ? ? }
? ? ? ? slurp, err := ioutil.ReadAll(part)
? ? ? ? if err != nil {
? ? ? ? ? ? errc <- errors.Wrap(err, "failed to read part")
? ? ? ? ? ? return
? ? ? ? }
? ? ? ? resc <- slurp
? ? }
}
func main() {
? ? cmd := exec.Command("python", "output.py")
? ? cmd.Stderr = os.Stderr
? ? pr, err := cmd.StdoutPipe()
? ? if err != nil {
? ? ? ? log.Fatal(err)
? ? }
? ? var wg sync.WaitGroup
? ? wg.Add(1)
? ? resc := make(chan []byte)
? ? errc := make(chan error)
? ? go readCommand(pr, &wg, resc, errc)
? ? if err := cmd.Start(); err != nil {
? ? ? ? log.Fatal(err)
? ? }
? ? for {
? ? ? ? select {
? ? ? ? case err, ok := <-errc:
? ? ? ? ? ? if !ok {
? ? ? ? ? ? ? ? errc = nil
? ? ? ? ? ? ? ? break
? ? ? ? ? ? }
? ? ? ? ? ? if err != nil {
? ? ? ? ? ? ? ? log.Fatal(errors.Wrap(err, "error from goroutine"))
? ? ? ? ? ? }
? ? ? ? case res, ok := <-resc:
? ? ? ? ? ? if !ok {
? ? ? ? ? ? ? ? resc = nil
? ? ? ? ? ? ? ? break
? ? ? ? ? ? }
? ? ? ? ? ? fmt.Printf("Part from goroutine: %q\n", res)
? ? ? ? }
? ? ? ? if errc == nil && resc == nil {
? ? ? ? ? ? break
? ? ? ? }
? ? }
? ? cmd.Wait()
? ? wg.Wait()
}
排名不分先后:
與其使用 an
io.Pipe()
作為命令的Stdout
,不如向命令詢問(wèn)它的StdoutPipe()
。cmd.Wait()
將確保它為您關(guān)閉。設(shè)置
cmd.Stderr
為os.Stderr
以便您可以查看 Python 程序生成的錯(cuò)誤。我注意到只要 Python 程序?qū)懭霕?biāo)準(zhǔn)錯(cuò)誤,這個(gè)程序就會(huì)掛起?,F(xiàn)在它沒(méi)有:)
不要將其設(shè)為
WaitGroup
全局變量;將對(duì)它的引用傳遞給 goroutine。與其
log.Fatal()
在 goroutine 內(nèi)部執(zhí)行 ing,不如創(chuàng)建一個(gè)錯(cuò)誤通道來(lái)將錯(cuò)誤傳回給main()
.與其在 goroutine 中打印結(jié)果,不如創(chuàng)建一個(gè)結(jié)果通道將結(jié)果傳回給
main()
.確保通道關(guān)閉以防止阻塞/goroutine 泄漏。
將 goroutine 分離到一個(gè)適當(dāng)?shù)暮瘮?shù)中,使代碼更易于閱讀和遵循。
在這個(gè)例子中,我們可以在我們的 goroutine 內(nèi)部創(chuàng)建
multipart.Reader()
,因?yàn)檫@是我們代碼中唯一使用它的部分。請(qǐng)注意,我使用
Wrap()
fromerrors
包來(lái)為錯(cuò)誤消息添加上下文。當(dāng)然,這與您的問(wèn)題無(wú)關(guān),但這是一個(gè)好習(xí)慣。
該for { select { ... } }
部分可能令人困惑。
- 1 回答
- 0 關(guān)注
- 188 瀏覽
添加回答
舉報(bào)