post Image
Goでflagを使ってコマンドライン引数を扱う

多分一億番煎じくらいの内容:tea:
記事としての価値はまあ置いといて:raised_hand:
せっかくやったので整理のために書きます:bulb:

公式ドキュメント
https://golang.org/pkg/flag/

非フラグの取得

Parse()を呼んだ後にArgs()[]stringとして取得できます。

sample1_1.go
package main

import (
    "flag"
    "fmt"
)

func main() {
    flag.Parse()
    args := flag.Args()
    fmt.Println(args)
}
実行例1-1
$ 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として取り出します。

sample1_2.go
package main

import (
    "flag"
    "fmt"
)

func main() {
    flag.Parse()
    fmt.Println(flag.Arg(0), flag.Arg(1))
}
実行例1-2-1
$ go run sample1_2.go hoge fuga
hoge fuga

範囲外アクセスしたつもりが落ちたりはしませんでした。空文字列が返ってくるっぽいです。

実行例1-2-2
$ go run sample1_2.go 1
1

フラグの取得

型名()あるいは型名Var()でフラグの定義をした後Parse()でそれぞれの変数に取得できます。
定義は(フラグ名、デフォルト値、ヘルプメッセージ)の3つからなります。
型名()を使った場合、指定した型のポインタが返ってきます。

sample2_1.go
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)
}
実行例2-1-1
$ go run sample2_1.go -int 2 -str hello -bool true
2 hello true

フラグが指定されない場合はデフォルト値が入ります。

実行例2-1-2
$ go run sample2_1.go
0 default false

型名Var()を使った場合、引数で渡した変数にバインドされます。

sample2_2.go
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)
}
実行例2-2-1
$ go run sample2_2.go -dur 1h -float 2.3
1h0m0s 2.3

パースできない値を渡すと怒られます。駄目な理由を教えてくれるので親切です。ついでにフラグの種類とデフォルト値も表示してくれます。

実行例2-2-2
$ 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)

定義していないフラグを渡しても怒られます。

実行例2-2-3
$ go run sample2_2.go -unkown yeah
flag provided but not defined: -unkown
(以下略)

フラグの書き方は-flag valueでも-flag=valueでも大丈夫です。ただしboolの場合は-flag=valueの形式を使ったほうが良いみたいです(下の実行例3参照)。

実行例2-2-4
$ go run sample2_2.go -dur=1m -float .5
1m0s 0.5

-hでヘルプを表示できます。

実行例2-2-5
$ go run sample2_2.go -h
Usage of (略):
  -dur duration
        duration flag (default 1s)
  -float float
        float flag (default 0.1)

個数を数える

非フラグはNArg()、フラグはNFlag()でそれぞれ個数を数えられます。

sample3.go
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())
}
実行例3
$ 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超便利だな!!!って思いました:sparkles:
今までコマンドライン引数って文字列を頑張ってパースしないといけないものだとばかり思っていたもので:sweat_smile:
言語にあらかじめこういったパッケージが用意されているのはホント素晴らしい:tada:


『 Go 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。