[go] 標準出力への書き込み内容を文字列として取得する

何らかの事情があってgoで標準出力への書き込み内容を文字列として取得したい場合の対処方法のご紹介。

標準出力の内容を取得する

実は、os.Stdoutを書き換えられるのでos.Pipe()で上書きしてパイプ経由で値を取得する。

tmpStdout := os.Stdout  // 標準出力を元に戻せるように保存
r, w, _ := os.Pipe()
os.Stdout = w // 標準出力の書き込み先を変更

println("標準出力への書き込み")

w.Close() // 閉じないと永遠に書き込みが終わらない
var buf bytes.Buffer
buf.ReadFrom(r) // バッファーに値をコピー

s = strings.TrimRight(buf.String(), "\n")  // バッファーから文字列へ変換

os.Stdout = tmpStdout // 標準出力を元に戻してあげる

もちろん標準エラー出力の場合もほぼ同様の手順で、値の取得ができる。

ちょっと便利な関数にする

こんな風に関数にしておけば引数に渡した関数内での標準出力への書き込み内容を文字列として取得できる。
元のスコープに戻ったときには標準出力も元どおり。

import "os"

func GetStdoutAsString(f func()) string {
  tmpStdout := os.Stdout
  defer func() {
    os.Stdout = tmpStdout
  }()
  r, w, _ := os.Pipe()
  os.Stdout = w

  f()
  w.Close()
  var buf bytes.Buffer
  buf.ReadFrom(r)
  return strings.TrimRight(buf.String(), "\n")
}

ログ系のテストを行う際に標準出力への書き込み内容をテストしたい場合なんかに使える。

以上、golangで標準出力の内容を取得する方法でした。

参考

https://qiita.com/zenizh/items/ff636f15da87dabebe6c