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

首先,我将命令构建为 exec.exe:


package main

import "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 main


import (

    "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:


1

12

232

http://img2.mukewang.com/64b506360001d35d02200173.jpg

我是否以错误的方式使用cmd管道?



喵喵时光机
浏览 157回答 3
3回答

海绵宝宝撒

该程序正在阻塞,因为子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)    }}

慕盖茨4494581

一种方法可以做到这一点cmd := exec.Command("...") // Change to your pathstdin, 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 bufgo func() {    io.Copy(buf, stdout)}()if err := cmd.Start(); err != nil {    panic(err)}stdin.Write([]byte("hello\n")) // Send \n to submitstdin.Write([]byte("world\n"))if err := cmd.Wait(); err != nil {    panic(err)}fmt.Fprint(os.Stdout, buf)结果:➜ go run main.goinput a valuehelloinput another valueworld

陪伴而非守候

您需要监听正在执行的程序的输出。当您写“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)    }
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go