如何将os.Stdout输出复制到字符串变量

Hau*_* Ma 1 go output

我有这样的功能:

package main

import (
    "fmt"
)

// PrintSomething prints some thing
func PrintSomething() {
    fmt.Println("print something")
}

func main() {
    PrintSomething()
}
Run Code Online (Sandbox Code Playgroud)

如何将PrintSomething包装到另一个函数调用CaptureSomething以将字符串"print something"保存到变量并返回它?

Cer*_*món 6

创建管道并将stdout设置为管道编写器.启动goroutine将管道读取器复制到缓冲区.完成后,关闭管道编写器并等待goroutine完成读取.将缓冲区作为字符串返回.

// 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
    }
Run Code Online (Sandbox Code Playgroud)

}

像这样使用它:

done := capture()
fmt.Println("Hello, playground")
capturedOutput, err := done()
if err != nil {
    // handle error
}
Run Code Online (Sandbox Code Playgroud)

操场的例子

  • 我要让`done`而不是`struct {}`来传递`error`,然后将它从io.Copy`或`r.Close`返回的错误发送给它,否则返回nil。然后,我将检查`&lt;-done`返回什么。好吧,在这种情况下,错误是不太可能发生的,但总比吹嘘忽略意外错误要好得多。 (2认同)