2018年12月26日水曜日

go-flags を使ってみた

概要

golang にはデフォルトでコマンドラインパーサ用のライブラリが用意されています
しかし更に強力なライブラリがサードパーティで公開されています
今回は go-flags というライブラリを簡単ですが使ってみました

環境

  • macOS 10.14.1
  • golang 1.11.2
  • go-flags 5de817a

インストール

  • go get github.com/jessevdk/go-flags

Getting Startedサンプルコード

とりあえず動かしてみましょう

package main

import (
    "fmt"
    flags "github.com/jessevdk/go-flags"
    "os"
)

type Options struct {
    Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information" required:"true"`
}

var opts Options

func main() {
    _, err := flags.Parse(&opts)
    if err != nil {
        os.Exit(1)
    }
    fmt.Printf("%v\n", opts.Verbose)
    fmt.Println("end")
}

struct でオプションの情報を定義します
short, long, description などヘルプに表示できる情報を定義できます
定義した struct の変数を準備します

そして flags.Parse にその変数のポインタを渡すことで引数の情報が struct に合わせてバインドされます
err じゃない場合は各 struct フィールドを参照できるようになっています

実行は

  • go build github.com/hawksnowlog/gf_test
  • go install github.com/hawksnowlog/gf_test
  • $GOPATH/bin/gf_test -v

でできます
今回の場合 required:"true" オプションを指定しているので指定しない場合はエラー文言 the required flag '-v, --verbose' was not specified) が表示されます
struct で指定可能なオプションはこちらに記載があります

パーサをカスタマイズする

例えば -h 指定時の Usage メッセージを変更してみます
ちなみにデフォルトは gf_test [OPTIONS] と表示されます

package main

import (
    "fmt"
    flags "github.com/jessevdk/go-flags"
    "os"
)

type Options struct {
    Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information" required:"true"`
}

var opts Options

func main() {
    parser := flags.NewParser(&opts, flags.Default)
    parser.Usage = "[opts]"
    _, err := parser.Parse()
    if err != nil {
        os.Exit(1)
    }
    fmt.Printf("%v\n", opts.Verbose)
    fmt.Println("end")
}

NewParser を使ってパーサを作成します
そして Usage プロパティの値を変更することで文言を変更できます
NewParser の 2 つ目の引数でパーサーのデフォルトの動作を指定できます
今回は flags.Default を指定しています
ここ に指定可能なデフォルトの定数があります

関数を呼び出す

オプション定義時に型ではなくコールバック用の関数を定義できます

package main

import (
    "fmt"
    flags "github.com/jessevdk/go-flags"
    "os"
)

type Options struct {
    Verbose []bool       `short:"v" long:"verbose" description:"Show verbose debug information" required:"true"`
    Name    func(string) `short:"n" long:"name" description:"Name parameter"`
}

var opts Options

func main() {
    opts.Name = func(n string) {
        fmt.Println(n)
    }
    parser := flags.NewParser(&opts, flags.Default)
    parser.Usage = "[opts]"
    _, err := parser.Parse()
    if err != nil {
        os.Exit(1)
    }
    fmt.Printf("%v\n", opts.Verbose)
    fmt.Println("end")
}

Name func(string) という感じで Options を定義します
そして Options の変数 opts に対して opts.Name でコールバック用の関数を定義してあげます
上記のコードの場合 main 内でないとsyntax error: non-declaration statement outside function body になるので注意してください

サブコマンドを定義する

オプションではなくサブコマンドも定義できます

package main

import (
    "fmt"
    flags "github.com/jessevdk/go-flags"
    "os"
)

type SubCmd struct {
}

func (sc *SubCmd) Execute(args []string) error {
    fmt.Println("subcmd")
    return nil
}

type Options struct {
    SubCmd SubCmd `command:"subcmd"`
}

var opts Options

func main() {
    parser := flags.NewParser(&opts, flags.Default)
    _, err := parser.Parse()
    if err != nil {
        os.Exit(1)
    }
}

struct でオプションを定義する際に command:"subcmd" を指定します
「subcmd」の部分はサブコマンド名になるので好きな名前を指定してください
ポイントは SubCmd struct の Execute 関数です
この引数と返り値で定義することでサブコマンドが指定されたときに Execute 関数が自動的に呼ばれます

最後に

簡単ですが go-flags の使ってみました
基本はコマンドラインツールを作るときに使う感じです

他にも初期化の方法はいろいろあります
.ini ファイルを使って外部のファイルにオプション情報を定義してそこからパーサを生成することもできるようです

参考サイト

0 件のコメント:

コメントを投稿