2013-10-29 51 views
1

我在努力去学习Go,我想我会从一个我想做一段时间的项目开始(但这似乎太“烦人”了)。基本的想法是,我有一个程序在stdin/stdout上与用户交互,我想写一个新的程序,以相同的方式与程序交互(就好像它是一个运行程序的人)。Go的持久性程序

现在这里的程序很简单,因为它是同步的:你输入一个命令,获得一些输出,然后它坐在那里等待下一批输入。这似乎并不困难,但我无法让这个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

为了进行测试,下面是源'e':http://pastebin.com/59Qc3bxy – Charles

回答

1

你最大的问题是你重新分配命令的标准输入,而不是管道。

这里有一个工作版本:

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) 
    } 
} 
0

你有点重新发明轮子,你想做的一切都可以通过fmt包来处理,所以只需要使用它并在需要的地方添加诸如随机数字检查器等额外的东西。

下面是如何实现这一点很容易的例子:http://play.golang.org/p/b9GNovSRFj

而对于一个快看,这个战略的主要功能:

var s string 
_, err := fmt.Scanf("%s", &s) 
if err != nil { 
    log.Fatal(err) 
} 
fmt.Println(s) 

注意,它不会因操场跑许可问题,但如果你在本地运行它应该可以正常工作。

+0

请在答案中包含代码的精髓。 – nemo

+0

这根本不会产生外部过程,我不确定它是如何与我的问题相关的。 – Charles