たとえば、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でこれを実行できますか?
管理できる場合は、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)
}
この答えは前のものと似ていますが、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
}
これはお勧めしませんが、os.Stdout
を変更することで実現できます。この変数はos.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)
}
アイデア全体はまったくお勧めできません(競合状態)が、os.Stdoutをあなたの例に似た/アナロジ的な方法で混乱させることができると思います。