@Konboi memo

主に技術に関してつらつらと。

Goのflag package で同じオプション名で複数の値を受け取る

はじめに

コマンドラインツールを作っていると同一オプションで複数の値を受け取りたい事があります

今回は -ignore hoge -ignore fuga の用に特定の文字列を結果から除きく ignore というオプション名で複数のStringを受け取りたい

という事にします

Goのflagが標準で提供しているもので複数の値を受け付けているのは

flag.Args() だけで今回の要件は満たすことができません

無いなら作る

では、どうするか

flag には flag.Var() という flagで定義しているValueを引数にとるメソッドがあります

flag.Value は

type Value interface {
    String() string
    Set(string) error
}

このように String()Set(string) error のinterfaceを満たすtypeを定義してあげます

interfaceを満たすtypeを定義する

String()Set(string) error を満たすtypeを実装すると 今回は複数のStringを受け付けたいので以下の用になります

type sliceString []string

func (*ss sliceString) String() string {
    return fmt.Sprintf(“%s”, *ss)
}

func (*ss sliceString) Set(value string) error {
    *ss = append(*ss, svalue)
    return nil
}

var ignoreStrings sliceString

これで flag.Typeを満たしつつ複数のstringを受け付けられるtypeの定義しそれの変数である ignoreStrings の準備ができた。

複数のintを受け付けたい場合は String()strconv.Itoa(someIntValue) などのようにしてstringを返す必要があります

定義した型を使う

定義できたので以下の用に flag.Var()を使うことで複数Stringを受けつることが出来る

func main () {
    flag.Var(&ignoreStrings, “ignore”, “Set ignore strings”
    flag.Parse()
}

こんな感じ(※ Go Playground 上では何も表示されません)

最後に

  • flag.Value を満たすtypeを定義すれば色んな引数がとれそう
  • 自分で定義するのが面倒なら alecthomas/kingpin とか使えばよさそう

Go言語によるWebアプリケーション開発

Go言語によるWebアプリケーション開発