golangのCLIツールで複数のオプションを受け取る

2020/07/28

golangでCLIツールを作るにあたり、同じオプションを複数指定する方法を調べましたよ。

CLIツールでは同じオプションを複数指定するようなケースはないと思っていたのですが、Dockerで複数のポートフォワーディングしたり、curlで複数のヘッダを指定するようなユースケースもあるので、golangでの実装方法を確認してみました。

flag を使った失敗例

まずは何も考えずに標準パッケージのflagを使ったパターンです。

この場合は以下の通り、複数のオプションを指定しても後から指定したオプションがのみが有効になってしまい、複数指定することができません。

% go run main.go
option =
% go run main.go --option aaa
option = aaa
% go run main.go --option aaa --option bbb
option = bbb

flag を使った成功例

flagでは複数の同じオプションを指定するために、Varという関数と、Valueというインタフェースが用意されています。 インタフェースを実装した型(今回の例だとstringFlags)を独自で用意することで、複数の同じオプションを受け取れるようになります。

以下のように複数のオプションを受け取れるようになりました。
この場合、オプションが1つしかない場合もスライスとして格納されます。

% go run main.go
option = []
% go run main.go --option aaa
option = [aaa]
% go run main.go --option aaa --option bbb
option = [aaa bbb]

urfave/cli を使った例

golangでCLIツールを作るときにはurfave/cliというサードパーティ製のパッケージがよく用いられるので、こちらでも試してみます。
urfave/cliには複数のオプションを受け取るための関数として、StringSliceIntSliceが用意されているので、簡単に実現可能です。

この場合も、オプションが1つでもスライスとして格納されます。

go run main.go
option = []
% go run main.go --option aaa
option = [aaa]
% go run main.go --option aaa --option bbb
option = [aaa bbb]

おわり

同じ名前で複数のオプションを指定する用途はそんなに多くないけど、実装方法がわかったので有事の際も一安心です。

golang

統計学の本を読みましたよ

Steamサマーセール2020です