funcstdoutPipe() { echo := exec.Command("echo", "-n", "the quick brown fox jumps over the lazy dog") pipe, err := echo.StdoutPipe() // 获取命令执行后的 pipe if err != nil { log.Fatal(err) } if err := echo.Start(); err != nil { log.Fatal(err) }
var buf bytes.Buffer for { out := make([]byte, 10) n, err := pipe.Read(out) // 读取命令管道内容 if err == io.EOF { break } if err != nil { log.Fatal(err) } if n > 0 { buf.Write(out[:n]) } } fmt.Printf("%q\n", buf.String()) // the quick brown fox jumps over the lazy dog }
// 多个 writer 将数据写入 pipe,一个 reader 读取数据 funcmain() { c := make(chanint) r, w := io.Pipe() go read(r, c)
buf := []byte("abcde") for i := 0; i < 5; i++ { p := buf[i : i+1] n, err := w.Write(p) if n != len(p) { log.Fatalf("wrote %d, got %d", len(p), n) } if err != nil { log.Fatalf("write: %v", err) } nn := <-c if nn != n { log.Fatalf("wrote %d, read got %d", n, nn) } }
w.Close() // 发送完毕手动 Close nn := <-c if nn != 0 { log.Fatalf("final read got %d", nn) } }
funcread(r io.Reader, c chanint) { for { var buf = make([]byte, 64) n, err := r.Read(buf) if err == io.EOF { c <- 0 break } if err != nil { log.Fatalf("read fail: %v", err) } fmt.Printf("[read]: %s\n", buf[:n]) c <- n } }
运行:
总结
进程间通信方式包括管道,信号,消息队列,共享内存,信号量和 socket 等方式,对应到 Go 实现是 io.Pipe,os.Signal,sync.Mutex,net pkg 等。本文简要解析了 Go 中 pipe 的实现,实际开发中它的场景比较冷门,比如像数据流的实时处理可以考虑使用。