多分一億番煎じくらいの内容
記事としての価値はまあ置いといて
せっかくやったので整理のために書きます
公式ドキュメント
https://golang.org/pkg/flag/
非フラグの取得
Parse()
を呼んだ後にArgs()
で[]string
として取得できます。
package main
import (
"flag"
"fmt"
)
func main() {
flag.Parse()
args := flag.Args()
fmt.Println(args)
}
$ go run sample1_1.go a b c
[a b c]
$ go run sample1_1.go 1 2 3
[1 2 3]
特定の要素だけ取り出したい場合はArg(int)
が使えます。こちらもstring
として取り出します。
package main
import (
"flag"
"fmt"
)
func main() {
flag.Parse()
fmt.Println(flag.Arg(0), flag.Arg(1))
}
$ go run sample1_2.go hoge fuga
hoge fuga
範囲外アクセスしたつもりが落ちたりはしませんでした。空文字列が返ってくるっぽいです。
$ go run sample1_2.go 1
1
フラグの取得
型名()
あるいは型名Var()
でフラグの定義をした後Parse()
でそれぞれの変数に取得できます。
定義は(フラグ名、デフォルト値、ヘルプメッセージ)の3つからなります。
型名()
を使った場合、指定した型のポインタが返ってきます。
package main
import (
"flag"
"fmt"
)
func main() {
var (
i = flag.Int("int", 0, "int flag")
s = flag.String("str", "default", "string flag")
b = flag.Bool("bool", false, "bool flag")
)
flag.Parse()
fmt.Println(*i, *s, *b)
}
$ go run sample2_1.go -int 2 -str hello -bool true
2 hello true
フラグが指定されない場合はデフォルト値が入ります。
$ go run sample2_1.go
0 default false
型名Var()
を使った場合、引数で渡した変数にバインドされます。
package main
import (
"flag"
"fmt"
"time"
)
func main() {
var (
d time.Duration
f float64
)
flag.DurationVar(&d, "dur", 1 * time.Second, "duration flag")
flag.Float64Var(&f, "float", 0.1, "float flag")
flag.Parse()
fmt.Println(d, f)
}
$ go run sample2_2.go -dur 1h -float 2.3
1h0m0s 2.3
パースできない値を渡すと怒られます。駄目な理由を教えてくれるので親切です。ついでにフラグの種類とデフォルト値も表示してくれます。
$ go run sample2_2.go -float str
invalid value "str" for flag -float: strconv.ParseFloat: parsing "str": invalid syntax
Usage of (略):
-dur duration
duration flag (default 1s)
-float float
float flag (default 0.1)
定義していないフラグを渡しても怒られます。
$ go run sample2_2.go -unkown yeah
flag provided but not defined: -unkown
(以下略)
フラグの書き方は-flag value
でも-flag=value
でも大丈夫です。ただしboolの場合は-flag=value
の形式を使ったほうが良いみたいです(下の実行例3参照)。
$ go run sample2_2.go -dur=1m -float .5
1m0s 0.5
-h
でヘルプを表示できます。
$ go run sample2_2.go -h
Usage of (略):
-dur duration
duration flag (default 1s)
-float float
float flag (default 0.1)
個数を数える
非フラグはNArg()
、フラグはNFlag()
でそれぞれ個数を数えられます。
package main
import (
"flag"
"fmt"
)
func main() {
flag.Int("int", 0, "int flag")
flag.String("str", "default", "string flag")
flag.Bool("bool", false, "bool flag")
flag.Parse()
fmt.Println(flag.NArg(), flag.NFlag())
}
$ go run sample3.go -int 1 -str foo -bool=true a b
2 3
$ go run sample3.go -int 1 -str foo -bool true a b
3 3
$ go run sample3.go -bool true -int 1 -str foo a b
7 1
$ go run sample3.go a b c -bool=true -str foo
6 0
$ go run sample3.go -bool=true -str foo a b c
3 2
$ go run sample3.go a b c
3 0
$ go run sample3.go -bool=true -str foo
0 2
フラグがboolかつ後ろに引数が続く場合、-flag=value
の形式で書かないとフラグの値として認識してくれませんでした。
また、非フラグはフラグより後ろに書かないといけないみたいです。
おわりに
flag超便利だな!!!って思いました
今までコマンドライン引数って文字列を頑張ってパースしないといけないものだとばかり思っていたもので
言語にあらかじめこういったパッケージが用意されているのはホント素晴らしい