多分一億番煎じくらいの内容![]()
記事としての価値はまあ置いといて![]()
せっかくやったので整理のために書きます![]()
公式ドキュメント
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超便利だな!!!って思いました![]()
今までコマンドライン引数って文字列を頑張ってパースしないといけないものだとばかり思っていたもので![]()
言語にあらかじめこういったパッケージが用意されているのはホント素晴らしい![]()