为了账号安全,请及时绑定邮箱和手机立即绑定

如何在golang中使用os/exec处理用户输入?我无法停止输入阶段

如何在golang中使用os/exec处理用户输入?我无法停止输入阶段

Go
喵喵时光机 2023-07-17 17:12:54
首先,我将命令构建为 exec.exe:package mainimport "fmt"func main() {    var input string    fmt.Println("input a value")    fmt.Scanln(&input)    fmt.Println(input)    fmt.Println("input another value")    fmt.Scanln(&input)    fmt.Println(input)}然后我想使用 os/exec 包来运行它:package mainimport (    "fmt"    "os/exec")func main() {    cmd := exec.Command("G:\\go_workspace\\GOPATH\\src\\pjx\\modules\\exec\\exec")    stdin, e := cmd.StdinPipe()    if e != nil {        panic(e)    }    stdout, e := cmd.StdoutPipe()    if e != nil {        panic(e)    }    if e:=cmd.Start();e!=nil {        panic(e)    }    stdin.Write([]byte("hello"))    var buf = make([]byte, 512)    n, e := stdout.Read(buf)    if e != nil {        panic(e)    }    fmt.Println(string(buf[:n]))    if e := cmd.Wait(); e != nil {        panic(e)    }}最后我运行它,结果将在用户输入阶段暂停,例如:(如果图片未加载,它们会在输入阶段暂停)please input a value:112232我是否以错误的方式使用cmd管道?
查看完整描述

3 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

该程序正在阻塞,因为子fmt.Scanln进程中的 正在等待该\n字符(anEOF也会导致它返回)。为了避免阻塞,您的输入应该包含两个\ns,或者您可以只调用“stdin.Close()”来指示输入流已完成。


并且由于子流程多次调用Scanln和Println,因此单次调用stdout.Read可能无法读取子流程的完整输出。您可以继续调用stdout.Read()直到io.EOF返回错误,或者只使用ioutil.ReadAll.


func main() {

    cmd := exec.Command("G:\\go_workspace\\GOPATH\\src\\pjx\\modules\\exec\\exec")


    stdin, e := cmd.StdinPipe()

    if e != nil {

        panic(e)

    }


    stdout, e := cmd.StdoutPipe()

    if e != nil {

        panic(e)

    }

    if e := cmd.Start(); e != nil {

        panic(e)

    }

    _, e = stdin.Write([]byte("hello\nworld\n"))

    if e != nil {

        panic(e)

    }

    stdin.Close()


    out, _ := ioutil.ReadAll(stdout)

    // or you can use a loop

    //for {

    //  var buf = make([]byte, 512)

    //  n, e := stdout.Read(buf)

    //  if e == io.EOF {

    //      break

    //  }

    //  if e != nil {

    //      panic(e)

    //  }

    //  fmt.Println(string(buf[:n]))

    //}


    fmt.Println(string(out))


    if e := cmd.Wait(); e != nil {

        panic(e)

    }

}


查看完整回答
反对 回复 2023-07-17
?
慕盖茨4494581

TA贡献1850条经验 获得超11个赞

一种方法可以做到这一点


cmd := exec.Command("...") // Change to your path

stdin, err := cmd.StdinPipe()

if err != nil {

    panic(err)

}

stdout, err := cmd.StdoutPipe()

if err != nil {

    panic(err)

}


buf := bytes.NewBuffer(nil)

// read the stdout continuously in a separate goroutine and capture it in buf

go func() {

    io.Copy(buf, stdout)

}()


if err := cmd.Start(); err != nil {

    panic(err)

}


stdin.Write([]byte("hello\n")) // Send \n to submit

stdin.Write([]byte("world\n"))


if err := cmd.Wait(); err != nil {

    panic(err)

}


fmt.Fprint(os.Stdout, buf)

结果:


➜ go run main.go

input a value

hello

input another value

world


查看完整回答
反对 回复 2023-07-17
?
陪伴而非守候

TA贡献1757条经验 获得超8个赞

您需要监听正在执行的程序的输出。当您写“hello”时,程序可能仍在写入其标准输出。尝试这个:


    go func() {

        in := bufio.NewReader(stdout)

        for {

            s, err := in.ReadString('\n')

            if err != nil {

                return

            }

            fmt.Println(s)

        }

    }()


    if e := cmd.Start(); e != nil {

        panic(e)

    }


    stdin.Write([]byte("hello\n"))

    stdin.Write([]byte("hello2\n"))

    if e := cmd.Wait(); e != nil {

        panic(e)

    }


查看完整回答
反对 回复 2023-07-17
  • 3 回答
  • 0 关注
  • 156 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信