関連記事
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。
たまに、自分のプログラムの挙動にて「そのまま実行されている」場合と「パイプやリダイレクトされている」場合で出力形式を変えたい場合があります。
Linux(UNIX)の世界では、昔から isatty(3) というライブラリ関数が用意されているので、よくそれを利用して判定しますね。
んで、Goでもちょっと使いたいときがあったので、ライブラリ探してみたら mattn さんの go-isatty パッケージを発見。
ちなみに、isatty(3)という関数名をよく is-atty って感じで読む人いますが、この関数は is-a-tty って意味です。
そのまんま、「ttyですか?」って意味ですね。
サンプル
isatty/main.go
package main import ( "log" "os" "github.com/mattn/go-isatty" ) func main() { log.SetFlags(0) log.SetPrefix(">>> ") // isatty(3) は、指定したファイルディスクリプタが端末(tty)を参照しているかをチェックする関数. // そのディスクリプタが端末を指している場合は 1, それ以外は 0 を返す. // go-isattyパッケージは、Goにてtty判定を利用する場合に最も利用されているパッケージ. // // - ディスクリプタ自体が無効な場合(開かれていない/存在しない)は0を返し、errnoにEBADFが設定 // - ディスクリプタが存在するが「端末ではない」(例えば通常のファイルやパイプなど)場合は0を返し、errnoにENOTTYが設定 // // OSがLinuxの場合、内部で unix.IoctlGetTermios(int(fd), unix.TCGETS) が呼び出されている. // ioctl(2)にTCGETSを渡すと指定のディスクリプタが指す端末情報を取得できる. // // #include <sys/ioctl.h> // #include <termios.h> // // struct termios tty = {}; // ioctl(1, TCGETS, &tty); // // ちなみに、isattyという名前は is-atty ではなく、is-a-tty という意味。 // // REF: https://man7.org/linux/man-pages/man3/isatty.3.htm switch isatty.IsTerminal(os.Stdout.Fd()) { case true: // 端末に接続されている log.Println("Terminal") default: // 端末に接続されていない log.Println("Pipe or Redirect") } }
Taskfile.yml
# https://taskfile.dev version: '3' tasks: default: cmds: - go build -o app main.go - defer: rm -f app - ./app - ./app | tee - ./app > out.txt - defer: rm -f out.txt - echo hello | ./app
実行結果
$ task task: [default] go build -o app main.go task: [default] ./app >>> Terminal task: [default] ./app | tee >>> Pipe or Redirect task: [default] ./app > out.txt >>> Pipe or Redirect task: [default] echo hello | ./app >>> Terminal task: [default] rm -f out.txt task: [default] rm -f app
ちゃんと、パイプとリダイレクトの場合に判定出来ていますね。
参考情報
Goのおすすめ書籍
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。






