我正在努力学习Go,我想我会从一个我想做的项目开始一段时间(但这似乎太'繁琐'来打扰)。基本的想法是我有一个程序在stdin / stdout上与用户交互,我想编写一个新程序,它以相同的方式与程序交互(就好像它是一个运行程序的人)。 / p>
现在这里的程序很简单,因为它是同步的:你输入一个命令,得到一些输出,然后它就在那里等待下一批输入。这似乎并不那么难,但我无法让这个I / O骨架工作。
package main
import (
"os/exec"
"time"
"bufio"
"math/rand"
"fmt"
"strings"
)
func main() {
cmd := exec.Command("e") // A simple program that echos input until it becomes "exit"
progin, err := cmd.StdoutPipe()
if err != nil {
fmt.Println("Trouble with e's stdout")
panic(err)
}
err = cmd.Start()
if err != nil {
fmt.Println("Trouble starting e")
panic(err)
}
r := rand.New(rand.NewSource(99))
buf := bufio.NewReader(progin)
for {
// Write stuff
var toProg string
if (r.Float64() < .1) {
toProg = "exit"
} else {
toProg = fmt.Sprintf("%d", r.Int)
}
fmt.Println("Printing: ", toProg)
cmd.Stdin = strings.NewReader(toProg + "\n")
// Read stuff
time.Sleep(500 * time.Millisecond) // give the program time to generate output
input, err := buf.ReadString('\n')
if err != nil {
fmt.Println("I did *not* like that: ", input)
panic(err)
}
fmt.Println("Received: ", input)
}
}
任何参赛者?
答案 0 :(得分:1)
你最大的问题是你要重新分配命令的Stdin,而不是管道。
这是一个有效的版本:
package main
import (
"bufio"
"fmt"
"math/rand"
"os/exec"
"time"
)
func main() {
cmd := exec.Command("./e") // A simple program that echos input until it becomes "exit"
progin, err := cmd.StdoutPipe()
if err != nil {
fmt.Println("Trouble with e's stdout")
panic(err)
}
progout, err := cmd.StdinPipe()
if err != nil {
fmt.Println("Trouble with e's stdin")
panic(err)
}
err = cmd.Start()
if err != nil {
fmt.Println("Trouble starting e")
panic(err)
}
r := rand.New(rand.NewSource(99))
buf := bufio.NewReader(progin)
for {
// Write stuff
var toProg string
if r.Float64() < .1 {
toProg = "exit"
} else {
toProg = fmt.Sprintf("%d", r.Int())
}
fmt.Println("Printing: ", toProg)
progout.Write([]byte(toProg + "\n"))
// Read stuff
time.Sleep(500 * time.Millisecond) // give the program time to generate output
input, err := buf.ReadString('\n')
if err != nil {
fmt.Println("I did *not* like that: ", input)
panic(err)
}
fmt.Println("Received: ", input)
}
}
并且e.go有一些修正:
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
for {
buf := bufio.NewReader(os.Stdin)
input, err := buf.ReadString('\n')
if err != nil {
fmt.Println("Echo failed: ", input)
panic(err)
}
if strings.HasPrefix(input, "exit") {
fmt.Println("Bye!")
return
}
fmt.Print(input)
}
}
答案 1 :(得分:0)
你有点重新发明轮子,你想要做的一切都可以通过fmt
包处理,所以只需使用它并添加额外的东西,比如随机数检查器所需的位置。 / p>
以下是如何轻松实现此目标的示例:http://play.golang.org/p/b9GNovSRFj
快速浏览一下这个策略的主要功能:
var s string
_, err := fmt.Scanf("%s", &s)
if err != nil {
log.Fatal(err)
}
fmt.Println(s)
请注意,由于权限问题,它不会在操场上运行,但如果您在本地运行它,它应该可以正常工作。