Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Go, how do I capture stdout of a function into a string?

Tags:

stdout

go

In Python, for example, I can do the following:

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

Can you do this in Go?

like image 405
Andres Riofrio Avatar asked May 06 '12 19:05

Andres Riofrio


2 Answers

I agree you should use the fmt.Fprint functions if you can manage it. However, if you don't control the code whose output you're capturing, you may not have that option.

Mostafa's answer works, but if you want to do it without a temporary file you can use os.Pipe. Here's an example that's equivalent to Mostafa's with some code inspired by Go's testing package.

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)
}
like image 163
Evan Shaw Avatar answered Nov 17 '22 09:11

Evan Shaw


This answer is similar to the previous ones but looks cleaner by using 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
}
like image 25
mattes Avatar answered Nov 17 '22 08:11

mattes