2013-10-29 86 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