このエントリーをはてなブックマークに追加

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を使ってみました。

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