Go言語でコマンドラインオプションを扱う

Go言語でコマンドラインオプションの扱い方について調べました。

基礎

osパッケージのArgsを使うのが一番基礎的な関数です。

package main

import (
    "fmt"
    "os"
)

func main() {
    fmt.Println(os.Args)
}

結果はこうなります。

% go run main.go
[/tmp/go-build146822252/command-line-arguments/_obj/a.out]
%go run main.go hoge
[/tmp/go-build842086855/command-line-arguments/_obj/a.out hoge]
%go run main.go hoge hige
[/tmp/go-build161156361/command-line-arguments/_obj/a.out hoge hige]

配列の最初は実行プロセス自体ですね。go runで実行すると/tmp以下で実行さ れていることがわかります。

試しにbuildして実行してみます。

% go build
% ls
flag            main.go         main.go~
%./flag -h hige foo bar
[./flag  -h hige foo bar]

flagパッケージを使ってみる

もうちょっといい方法はflagパッケージを使う方法です。ドキュメントは こ こ にあります。

数を調べる

fmt.Println(flag.NArg())

NArgを使います。引数をなにもつけなければ 0 です。

parseする

// (name, default, help)
var f = flag.Int("f", 1234, "help message for f")
var s = flag.Bool("s", false, "help message for bool")
var long = flag.String("long-option", "default", "help message for long")
flag.Parse()

fmt.Println(*f)
fmt.Println(*s)
fmt.Println(*long)

としてみましょう。

% go build
%./flag --help
Usage of ./flag:
  -f=1234: help message for f
  -long-option="default": help message for long
  -s=false: help message for str
%./flag -f 11 --long-option=12 -s
11
true
12
%./flag -f 11 --long-option=loooong -s
11
true
loooong

help表示、boolで取得、longオプションが使えていますね。

なお、 -f でも --f でも -f 10 でも --f=10 でも、全部ちゃんと扱っ てくれます。

サブコマンドは?

残念ながらpythonのargparseのようなサブコマンド定義はできなさそうです。

でも、 optarg というパッ ケージがあり、これを使うともっと綺麗なhelp出力やサブコマンドなどが使え そうです。

(追記) goコマンドを見てみました。

こいつは、こんな感じに書かれていて、

for _, cmd := range commands {
        if cmd.Name() == args[0] && cmd.Run != nil {
                cmd.Flag.Usage = func() { cmd.Usage() }
                if cmd.CustomFlags {
                        args = args[1:]
                } else {
                        cmd.Flag.Parse(args[1:])
                        args = cmd.Flag.Args()
                }
                cmd.Run(cmd, args)  // ここで呼び出し
                exit()
                return
        }
}

各cmdごとにRun()というメソッドを実装しておき、そいつを呼び出して中でさ らに処理をしているわけですね。

まとめ

コマンドラインアプリを作る時はほぼ必須なコマンドラインオプションを解析 するパッケージ、flagを使ってみました。

最低限の機能は揃っているけれど、もう一声欲しかったかな、という印象を受 けました。

Comments

comments powered by Disqus