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
には複数のオプションを受け取るための関数として、StringSliceやIntSliceが用意されているので、簡単に実現可能です。
この場合も、オプションが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]
おわり
同じ名前で複数のオプションを指定する用途はそんなに多くないけど、実装方法がわかったので有事の際も一安心です。