GoのCLIでterminalから実行されたかどうかを判定したい

2024/05/06に公開

自分はGoで自作CLIツールをいくつも作っています。その中で特に以下のようなツールを作りたいとします。

  • 標準入力をpipeで受け取ったり、ファイル名をオプションで渡したり柔軟にできる

こういうツールを作ると以下の問題が発生することがあります。

  • 標準入力もファイル名も渡さない場合、プログラムは何もすることがない

まあ無視すればいいかもしれませんが、プログラムは起動するだけで何もできず、終了もできないので気持ち悪いです。こういうときにどうすればいいのかずっと分からなかったのですが、最近分かったので紹介します。

golang.org/x/termを利用する

https://pkg.go.dev/golang.org/x/term

こういうpackageがあるので使います。

term.IsTerminal(int(os.Stdin.Fd()))

これで標準入力がterminalかどうかが判定できます。この場合はpipeで標準入力が外部から渡されていたらfalse、直接だったらtrueを返します。os.Stdoutの場合はredirectしていたらfalseになります。

注意するべきなのはこの関数はテスト実行中はfalseになるので、trueにする方法がなさそう(分かる人がいたら教えてください。ソースコードのテストを手元で実行してみようと思いましたが、自分はうまいかなかったです)なので、この関数の返値は外から渡せるようにするべきです。そうすればテストをすることができるはずです。

Discussion