我有一个颇具挑战性的情况,我需要在系统命令stout中写入它输出的相同stdout(在另一个运行的程序中),下面是一个代表我的意思的示 routine 序:

package main

import (
    "bufio"
    "fmt"
    "math/rand"

    "os"
)

func main() {
    rand.Seed(time.Now().Unix())
    var greetings []string = []string{"hi", "hola", "bonjour", "hallo", "whats up"}
    var greeting string = greetings[rand.Intn(len(greetings))]
    fmt.Println(greeting)

    reader := bufio.NewReader(os.Stdin)
    message, _ := reader.ReadString('\n')
    if message == greeting+"\n" {
        fmt.Println("nice to meet you!")
    } else {
        fmt.Println("oops!")
    }
}

由于您使用随机问候语打招呼,因此您必须读取标准输出,将其发送到标准输入,并捕获它是否是正确答案.我试过使用stdinPipes,但它在等待stdin关闭时冻结,因为我认为它只适用于命令运行的开始,所以对于正在运行的程序来说,它一直不适用于我……

我感谢任何人的帮助!

编辑

我想添加一些我想要做的事情,我也try 了不使用通道,但这似乎对结果没有影响,它只是冻结,等待stdin关闭,我需要在关闭stdin之前先获取stdout,因为它包括:

package main

import (
    "io"
    "os/exec"
)

func main() {
    cmd := exec.Command("./executable_program")
    stdout, _ := cmd.StdoutPipe()
    stdin, _ := cmd.StdinPipe()

    var c chan []byte = make(chan []byte)

    cmd.Start()
    go func() {
        b, _ := io.ReadAll(stdout)
        c <- b
    }()

    stdin.Write(<-c)
    stdin.Close()

    cmd.Wait()
}

推荐答案

您可以使用管道将stdout连接到您执行的程序的stdin:

package main

import (
    "io"
    "os/exec"
)

func main() {
    r, w := io.Pipe()

    cmd := exec.Command("<name-of-program-to-run>")
    cmd.Stdin = r 
    cmd.Stdout = w 

    cmd.Run()
}

要实际了解这一点,首先让我们准备一个测试程序,由上面的程序执行.这个测试程序只需将一行打印到stdout,然后读取每一行stdin并将其打印到stdout,直到关闭stdin.

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    fmt.Fprint(os.Stdout, "priming the pump!\n")
    s := bufio.NewScanner(os.Stdin)
    for s.Scan() {
        line := s.Text()
        fmt.Fprint(os.Stdout, line+"\n")
    }   
}

然后,我们修改初始程序以打印遍历管道的字节,这样我们就可以看到发生了什么.

package main

import (
    "fmt"
    "io"
    "os/exec"
)

func main() {
    r, w := io.Pipe()

    sr := &readSpy{r: r}
    wr := &writeSpy{w: w}

    cmd := exec.Command("./test-program")
    cmd.Stdin = sr
    cmd.Stdout = wr

    cmd.Run()
}

type readSpy struct {
    r io.Reader
}

func (s *readSpy) Read(d []byte) (int, error) {
    size, err := s.r.Read(d)
    fmt.Println("readSpy read", string(d[:size]))
    return size, err
}

type writeSpy struct {
    w io.Writer
}

func (s *writeSpy) Write(d []byte) (int, error) {
    size, err := s.w.Write(d)
    fmt.Println("writeSpy wrote", string(d[:size]))
    return size, err
}

运行上面的命令,您将看到在无限循环中打印以下内容,这是有意义的,因为priming the pump!字符串被打印到stdout,并直接反馈到测试程序的stdin:

writeSpy wrote priming the pump!

readSpy read priming the pump!

...repeated forever...

Go相关问答推荐

区分Terminal和Hook Zerolog Go中的错误级别日志(log)输出

Golang应用程序:所请求的资源上不存在HTTP-Control-Allow-Origin标头

如何获取集群外go Kubernetes客户端的当前命名空间?

无效操作:v > max(类型参数 T 与 > 不可比较)

go-jwt 令牌验证错误 - 令牌签名无效:密钥类型无效

当我使用 CircleCI 构建 Go Image 时,我得到runtime/cgo: pthread_create failed: Operation not allowed

为什么我只收到部分错误而不是我启动的 goroutines 的所有错误?

Go泛型:无效的复合文字

设置指向空接口的指针

emersion/go-imap - imap.FetchRFC822:无效内存地址或零指针取消引用

如何使用 fyne Go 使用 canvas.NewText() 使文本可滚动

数据流中的无根单元错误,从 Golang 中的 PubSub 到 Bigquery

为什么当我忽略 template.New() 程序可以成功运行?

将shell输出绑定到Go中的 struct 的最佳方法?

Golang grpc go.mod 问题

关系不存在 GORM

Golang - 无法从 pipped Windows 命令中获取结果

如何在循环中旋转图像以便在 golang 中创建 GIF?

如何从字符串中删除多个换行符`\n`但只保留一个?

Go 错误:Is() 和 As() 声称是递归的,是否有任何类型实现错误接口并支持这种递归 - 无错误?