jessevdk/go-flagsでサブコマンドを実装する
Go言語を用いてコマンドラインツールを開発する際、皆さんはフラグのパースやサブコマンドの実装にどんなパッケージを使用していますか?標準のflagパッケージのほか、、spf13/cobra 、alecthomas/kingpin などもよく使われているようです。 私は専ら、jessevdk/go-flags (以下go-flags)を使用しています。 go-flagsはその名の通り、基本的にはオプション/フラグの解析用パッケージで、ドキュメント もフラグ解析に関するものがほとんどです。 しかし、go-flagsでは、サブコマンドの実装も可能です。今回はこれに焦点を当ててご紹介していきます。 go-flagsでは、親コマンドにサブコマンドを登録する、という形でサブコマンドを実装していきます。サブコマンドは構造体として実装し、それぞれがオプションを格納する構造体を兼ねる形となります。 終端の、実際に何かの動作をするコマンドは Commander interfaceを実装している必要がありますが、中間のサブコマンド(docker containerのような、グルーピングのためのサブコマンド)はこれを実装していなくても構いません。 Commander interfaceの定義は次のようになっています。 1 2 3 type Commander interface { Execute(args []string) error } 非常に単純ですね。argsにはコマンドでパースされなかったあまりの引数が渡されます。 実際の実装例を見てみましょう。 1 2 3 4 5 6 7 8 type subcommand struct { verbose bool `short:"v" long:"verbose"` } func (cmd *subcommand) Execute(args []string) error { // some exec return nil } サブコマンドを実装したら、親のコマンドにサブコマンドとして登録します。 ドキュメントを見ると、Command構造体に登録する関数があること、Parser構造体はCommand構造体が埋め込まれていること、がわかります。 通常、go-flagsパッケージを使用する場合はパッケージグローバルのParse関数を使用することが多いと思うのですが、サブコマンドを実装する場合はトップレベルのパーサーを自分で作る必要があります。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 type options struct { // ....