Go言語のflagパッケージを使う

Go言語でコマンドラインオプションを扱う - そこはかとなく書くよん。

に触発されたので、flagパッケージについて自分で使ってみてハマったところを書いておく。

コマンドラインオプションの略称を登録する

flag.IntVar()などのXxxVar()を使う。

これで -boolでも-bでも同じ変数にフラグの結果が反映されるようになる。

$ go run flag_shorthand.go -bool -int 100 -string hoge
bool flag   = true
int flag    = 100
string flag = hoge

$ go run flag_shorthand.go -b -i 100 -s hoge
bool flag   = true
int flag    = 100
string flag = hoge

コマンドラインオプションを最後まで解析する

flag.Parse()の解析は、非フラグ引数(頭に"-"の付いた引数)の前、もしくは"--"の後で打ち切られる。

Flag parsing stops just before the first non-flag argument ("-" is a non-flag argument) or after the terminator "--".

http://golang.org/pkg/flag/#pkg-overview

そのため、以下のようなコマンドラインだとxxxの部分でフラグ解析が打ち切られるため、フラグが設定されない。

$ go run flag_shorthand.go xxx -b -i 100 -s hoge
bool flag   = false
int flag    = 0
string flag = blank

そこで、flag.NewFlagSet()を用いて以下のような処理を書くことでフラグ引数の前にxxxのような非フラグ引数があっても最後までフラグ解析を行わせることができる。

flag.NewFlagSet()でFlagSetを生成した場合、Parse()には解析する文字列のスライスが引数として要求される。その引数の開始インデックスを1ずつ進めてやればいい。

$ go run flag_checkall.go xxx -b -i 100 -s hoge
bool flag   = true
int flag    = 100
string flag = hoge

外部パッケージでoptargなるものがあるそうなので、後で試してみよう。