1

私は Go を学ぼうとしていて、しばらくやりたかったプロジェクトから始めようと思っていました (しかし、それは面倒すぎて気にすることができませんでした)。本質的なアイデアは、stdin/stdout でユーザーと対話するプログラムがあり、同じ方法でプログラムと対話する新しいプログラムを書きたいということです (あたかもプログラムを実行している人であるかのように)。

ここでのプログラムは単純で、同期的です。コマンドを入力し、出力を取得すると、次のバッチの入力を待機します。それほど難しくはないように思えましたが、この 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)

    }
}

テイカーはいますか?

4

2 に答える 2

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)
    }
}
于 2013-10-29T21:30:46.463 に答える
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)

権限の問題によりプレイグラウンドでは実行されませんが、ローカルで実行すると問題なく動作するはずです。

于 2013-10-29T21:02:25.640 に答える