TL;DR: 標準パッケージ<code>text/tabwriter</code> を使用する

コマンドラインツールで標準出力を良い感じにそろえて出力したい場合があります。 例えば、docker では、以下の様に出力されます。

$ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
8caad461b4a4        redis               "docker-entrypoint.s…"   5 days ago          Up 5 days           0.0.0.0:6379->6379/tcp   redis-svr
329c9f9be035        mysql               "docker-entrypoint.s…"   5 days ago          Up 5 days           0.0.0.0:3306->3306/tcp   mysql-svr

このような map、あるいは構造体の配列 の様なものを、きれいに表形式の様に列をそろえて出力したい場合に便利なのが標準パッケージの<code>text/tabwriter</code> です。 その名の通り、タブ区切りの文字列を良い感じに出力してくれるパッケージです。

text/tabwriterで定義されているのはいくつかの設定用定数 と、<code>Writer</code>構造体 のみです。 Writerは(勿論)<code>io.Writer</code>インターフェース を実装しています。

使用方法は通常のio.Writerとはすこし変わっていて、最初に<code>Writer.Init()</code> で初期化し、任意回数<code>Writer.Write()</code> で書き込みをした後、<code>Writer.Flush()</code> で整形した文字列を出力します。 <code>NewWriter()</code> 関数はWriter構造体をnew()した後Init()するのと同等です。

Writer.Init()関数及びNewWriter()関数に与える引数は以下の様になっています。

名前内容
outputio.WriterFlush()したときの出力先
minwidthint1セルあたりの最小幅(パディングを含む)
tabwidthintタブ文字の幅(スペースの個数と等しい)
paddingintパディング1
padcharbyteパディング文字2
flagsint調整用フラグ

最後の引数である、調整用フラグには0(標準状態)を与えるか、パッケージ定数 の論理和を用いて設定を与えます。

フラグ用定数 は以下のものが定義されています。

定数名意味
FilterHTMLHTMLタグや ’&’ で始まる特殊文字を1文字としてカウントする
StripEscapeエスケープ文字を取り除く
AlignRight右寄せにする
DiscardEmptyColumns最初の空列を無視する
TabIndentpadcharの値に関係なく、インデントにTAB文字を使用する
Debug列同士の間に縦棒`

example

source

w := tabwriter.NewWriter(os.Stdout, 0, 1, 1, ' ', tabwriter.AlignRight|tabwriter.Debug)
w.Write([]byte("alpha\tbeta\tgamma\t\n"))
for i := 0; i < 5; i++ {
    w.Write([]byte("foo\tbar\tbaz\t\n"))
}
w.Flush()

出力

 alpha| beta| gamma|
   foo|  bar|   baz|
   foo|  bar|   baz|
   foo|  bar|   baz|
   foo|  bar|   baz|
   foo|  bar|   baz|

  1. 文字列の幅に加えられる ↩︎

  2. ASCII文字で指定する ↩︎