如何在 Golang 中通过 STDIN/STDOUT 同时连接多个程序 reading/writing?
How to wire up multiple programs reading/writing via STDIN/STDOUT in Golang concurrently?
在高层次上,我想完成以下任务。每个框都是一个 运行 从 STDIN 读取并写入 STDOUT 的程序。我想编写一个 golang 程序来设置并运行它,以便所有 production/consumption 并行发生。我正在考虑使用 io.Pipe、频道和 os.Exec 等
+-----------+
| PROG-1 +-----------------------+
+---------> | | v
| +-----------+
| +-------+
+-----------+ | DIFF +----->
| GENERATOR | | |
+-----------+ +---+---+
| ^
| |
| +-----------+ |
| | | |
+---------> | PROG-2 +-----------------------+
+-----------+
这是一个尝试,但它似乎并没有可靠地工作,而且 "DIFF" 部分也没有实现。
package main
import (
"io"
"os"
"os/exec"
)
const UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
const LOWER = "abcdefghijklmnopqrstuvwxyz"
func runProg(r io.Reader, cmd *exec.Cmd) {
cmd.Stdin = r
cmd.Stdout = os.Stdout // I want this to go to a third prog call "diff".
cmd.Run()
}
func runIt(r io.Reader, prog1 *exec.Cmd, prog2 *exec.Cmd) {
r1, w1 := io.Pipe()
r2, w2 := io.Pipe()
go runProg(r1, prog1)
go runProg(r2, prog2)
go func() {
defer w1.Close()
defer w2.Close()
mw := io.MultiWriter(w1, w2)
io.Copy(mw, r)
}()
}
func main() {
generator := exec.Command("ls", "-l")
r, w := io.Pipe()
generator.Stdout = w
prog1 := exec.Command("tr", LOWER, UPPER)
prog2 := exec.Command("tr", UPPER, LOWER)
runIt(r, prog1, prog2)
generator.Run()
}
这里有几件事。您在创建所有这些管道时增加了工作量和复杂性。此外,运行 同时使用 Cmd.Start() 和 Cmd.Wait() 内置命令。
package main
import (
"fmt"
"io"
"os"
"os/exec"
)
const UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
const LOWER = "abcdefghijklmnopqrstuvwxyz"
func runProg(cmd *exec.Cmd) (w io.WriteCloser, err error) {
w, err := cmd.StdinPipe()
if err != nil {
fmt.Println(err)
}
cmd.Stdout = os.Stdout
err = cmd.Start()
}
func runIt(r io.Reader, prog1 *exec.Cmd, prog2 *exec.Cmd) {
w1, err := runProg(prog1)
if err != nil {
fmt.Println(err)
}
w2, err := runProg(prog2)
if err != nil {
fmt.Println(err)
}
go func() {
defer w1.Close()
defer w2.Close()
mw := io.MultiWriter(w1, w2)
io.Copy(mw, r)
}()
}
func main() {
generator := exec.Command("ls", "-l")
r, err := generator.StdoutPipe()
if err != nil {
fmt.Println(err)
}
prog1 := exec.Command("tr", LOWER, UPPER)
prog2 := exec.Command("tr", UPPER, LOWER)
runIt(r, prog1, prog2)
generator.Run()
err = prog1.Wait()
err1 := prog2.Wait()
if err != nil || err1 != nil {
fmt.Println(err, err1)
}
}
在高层次上,我想完成以下任务。每个框都是一个 运行 从 STDIN 读取并写入 STDOUT 的程序。我想编写一个 golang 程序来设置并运行它,以便所有 production/consumption 并行发生。我正在考虑使用 io.Pipe、频道和 os.Exec 等
+-----------+
| PROG-1 +-----------------------+
+---------> | | v
| +-----------+
| +-------+
+-----------+ | DIFF +----->
| GENERATOR | | |
+-----------+ +---+---+
| ^
| |
| +-----------+ |
| | | |
+---------> | PROG-2 +-----------------------+
+-----------+
这是一个尝试,但它似乎并没有可靠地工作,而且 "DIFF" 部分也没有实现。
package main
import (
"io"
"os"
"os/exec"
)
const UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
const LOWER = "abcdefghijklmnopqrstuvwxyz"
func runProg(r io.Reader, cmd *exec.Cmd) {
cmd.Stdin = r
cmd.Stdout = os.Stdout // I want this to go to a third prog call "diff".
cmd.Run()
}
func runIt(r io.Reader, prog1 *exec.Cmd, prog2 *exec.Cmd) {
r1, w1 := io.Pipe()
r2, w2 := io.Pipe()
go runProg(r1, prog1)
go runProg(r2, prog2)
go func() {
defer w1.Close()
defer w2.Close()
mw := io.MultiWriter(w1, w2)
io.Copy(mw, r)
}()
}
func main() {
generator := exec.Command("ls", "-l")
r, w := io.Pipe()
generator.Stdout = w
prog1 := exec.Command("tr", LOWER, UPPER)
prog2 := exec.Command("tr", UPPER, LOWER)
runIt(r, prog1, prog2)
generator.Run()
}
这里有几件事。您在创建所有这些管道时增加了工作量和复杂性。此外,运行 同时使用 Cmd.Start() 和 Cmd.Wait() 内置命令。
package main
import (
"fmt"
"io"
"os"
"os/exec"
)
const UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
const LOWER = "abcdefghijklmnopqrstuvwxyz"
func runProg(cmd *exec.Cmd) (w io.WriteCloser, err error) {
w, err := cmd.StdinPipe()
if err != nil {
fmt.Println(err)
}
cmd.Stdout = os.Stdout
err = cmd.Start()
}
func runIt(r io.Reader, prog1 *exec.Cmd, prog2 *exec.Cmd) {
w1, err := runProg(prog1)
if err != nil {
fmt.Println(err)
}
w2, err := runProg(prog2)
if err != nil {
fmt.Println(err)
}
go func() {
defer w1.Close()
defer w2.Close()
mw := io.MultiWriter(w1, w2)
io.Copy(mw, r)
}()
}
func main() {
generator := exec.Command("ls", "-l")
r, err := generator.StdoutPipe()
if err != nil {
fmt.Println(err)
}
prog1 := exec.Command("tr", LOWER, UPPER)
prog2 := exec.Command("tr", UPPER, LOWER)
runIt(r, prog1, prog2)
generator.Run()
err = prog1.Wait()
err1 := prog2.Wait()
if err != nil || err1 != nil {
fmt.Println(err, err1)
}
}