62

たとえば、Python では、次のことができます。

realout = sys.stdout
sys.stdout = StringIO.StringIO()
some_function() # prints to stdout get captured in the StringIO object
result = sys.stdout.getvalue()
sys.stdout = realout

Goでこれを行うことができますか?

4

4 に答える 4

71

fmt.Fprint機能を管理できる場合は、機能を使用する必要があることに同意します。ただし、キャプチャする出力のコードを制御しない場合は、そのオプションがない場合があります。

Mostafa の答えは機能しますが、一時ファイルなしで実行したい場合はos.Pipeを使用できます。これは、Go のテスト パッケージに触発されたコードを使用した Mostafa のものと同等の例です。

package main

import (
    "bytes"
    "fmt"
    "io"
    "os"
)

func print() {
    fmt.Println("output")
}

func main() {
    old := os.Stdout // keep backup of the real stdout
    r, w, _ := os.Pipe()
    os.Stdout = w

    print()

    outC := make(chan string)
    // copy the output in a separate goroutine so printing can't block indefinitely
    go func() {
        var buf bytes.Buffer
        io.Copy(&buf, r)
        outC <- buf.String()
    }()

    // back to normal state
    w.Close()
    os.Stdout = old // restoring the real stdout
    out := <-outC

    // reading our temp stdout
    fmt.Println("previous output:")
    fmt.Print(out)
}
于 2012-05-07T03:21:38.580 に答える
23

この回答は前の回答と似ていますが、io/ioutil を使用すると見やすくなります。

http://play.golang.org/p/fXpK0ZhXXf

package main

import (
  "fmt"
  "io/ioutil"
  "os"
)

func main() {
  rescueStdout := os.Stdout
  r, w, _ := os.Pipe()
  os.Stdout = w

  fmt.Println("Hello, playground") // this gets captured

  w.Close()
  out, _ := ioutil.ReadAll(r)
  os.Stdout = rescueStdout

  fmt.Printf("Captured: %s", out) // prints: Captured: Hello, playground
}
于 2015-03-30T05:35:52.170 に答える
15

これはお勧めしませんが、変更することで実現できますos.Stdout。この変数は typeos.Fileであるため、一時出力もファイルにする必要があります。

package main

import (
    "fmt"
    "io/ioutil"
    "os"
    "path/filepath"
)

func print() {
    fmt.Println("output")
}

func main() {
    // setting stdout to a file
    fname := filepath.Join(os.TempDir(), "stdout")
    fmt.Println("stdout is now set to", fname)
    old := os.Stdout // keep backup of the real stdout
    temp, _ := os.Create(fname) // create temp file
    os.Stdout = temp

    print()

    // back to normal state
    temp.Close()
    os.Stdout = old // restoring the real stdout

    // reading our temp stdout
    fmt.Println("previous output:")
    out, _ := ioutil.ReadFile(fname)
    fmt.Print(string(out))
}

これはあまりにも多くのハッキングであり、Go ではあまり慣用的ではないため、お勧めしません。関数に を渡し、io.Writerそれに出力を書き込むことをお勧めします。これは、ほぼ同じことを行うためのより良い方法です。

package main

import (
    "bytes"
    "fmt"
    "io"
    "os"
)

func print(w io.Writer) {
    fmt.Fprintln(w, "output")
}

func main() {
    fmt.Println("print with byes.Buffer:")
    var b bytes.Buffer
    print(&b)
    fmt.Print(b.String())

    fmt.Println("print with os.Stdout:")
    print(os.Stdout)
}
于 2012-05-06T22:03:02.253 に答える
3

全体のアイデアはまったくお勧めできません(競合状態)と思いますが、例に似た/類似した方法で os.Stdout をいじることができると思います。

于 2012-05-06T21:16:07.173 に答える