Create pipe and set stdout to the pipe writer. Start a goroutine to copy the pipe reader to a buffer. When done, close the pipe writer and wait for goroutine to complete reading. Return the buffer as a string.
// capture replaces os.Stdout with a writer that buffers any data written
// to os.Stdout. Call the returned function to cleanup and get the data
// as a string.
func capture() func() (string, error) {
r, w, err := os.Pipe()
if err != nil {
panic(err)
}
done := make(chan error, 1)
save := os.Stdout
os.Stdout = w
var buf strings.Builder
go func() {
_, err := io.Copy(&buf, r)
r.Close()
done <- err
}()
return func() (string, error) {
os.Stdout = save
w.Close()
err := <-done
return buf.String(), err
}
}
Use it like this:
done := capture()
fmt.Println("Hello, playground")
capturedOutput, err := done()
if err != nil {
// handle error
}
playground example