毎日ゴーフラグのライブラリーを行きます

簡単な紹介

では前の記事、私たちは、導入flagライブラリを。flagライブラリは、コマンドラインオプションを解析するために使用されます。しかし、flagいくつかの欠点があります。

  • 短いオプションのサポートを表示しません。もちろん、記事では、2つのオプションを述べた変数を達成同じ遠回りで共有することができますが、より複雑な書き込みをします。
  • より複雑な変数は、各オプションのタイプに応じて呼び出しに対応する、オプションを定義TypeまたはTypeVar関数。
  • デフォルトのサポートのみ限定されたデータタイプ、現在は基本タイプbool/int/uint/stringtime.Duration

これらの問題を解決するには、コマンドラインオプションを解析するために、多くのサードパーティのライブラリがあった、今日のヒーローは、go-flagsそのうちの一つです。私が見たのは初めてgo-flags読んでライブラリをpgwebの時間の源。

go-flags標準ライブラリが提供するよりもflagより多くのオプションを。これは、ラベル(構造体タグ)の構造を使用し、反射便利、簡単なインタフェースを提供します。その基本的な機能に加えて、だけでなく、豊富な機能を提供します。

  • 短いオプション(-v)と長いオプション(--verbose)をサポートしています。
  • サポートなどの短いオプションを、共同書きました-aux
  • 複数の値を設定するためのオプションを持ちます。
  • これは、すべての基本タイプとマップタイプ、あるいは機能をサポートしています。
  • 名前空間とオプショングループをサポートしています。
  • などなど。

上記の唯一のラフな説明であるgo-flags機能、の導入を回してみましょう。

クイックスタート

使用し始めてから学びます!のは、見てみましょうgo-flags基本的な使用を。

それはサードパーティのライブラリを使用する前にインストールする必要があるので、次のコマンドを実行してインストールします。

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

コード内で使用されるimportライブラリーに導入します:

import "github.com/jessevdk/go-flags"

完全なサンプルコードは次のとおりです。

package main

import (
  "fmt"

  "github.com/jessevdk/go-flags"
)

type Option struct {
  Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug message"`
}

func main() {
  var opt Option
  flags.Parse(&opt)

  fmt.Println(opt.Verbose)
}

使用するgo-flags一般的な手順は:

  • オプションの構造、オプションタブの設定情報構造を定義します。よるshortlong、設定の短期および長期のオプション名は、descriptionヘルプ情報を設定します。コマンドラインパラメータは、短いオプションを追加する前に、とき渡され-、プラス長い前にオプション--
  • オプション変数の宣言。
  • コールgo-flags解像度の分析方法を。

(私の環境はWin10 + Gitのバッシュで)コンパイルして、コードを実行します。

$ go build -o main.exe main.go

ショートオプション:

$ ./main.exe -v
[true]

ロングオプション:

$ ./main.exe --verbose
[true]

以降のVerboseフィールドは、各遭遇スライスタイプである-vか、--verbose追加しますtrueスライスに。

複数の短いオプション:

$ ./main.exe -v -v
[true true]

より長いオプション:

$ ./main.exe --verbose --verbose
[true true]

ショートオプション+長いオプション:

$ ./main.exe -v --verbose -v
[true true true]

短いオプションは、Co-書きました:

$ ./main.exe -vvv
[true true true]

基本的な特性

豊富なデータ型のサポート

go-flags標準ライブラリと比較するとflagデータ型のより豊富なセットをサポートしています。

  • (符号付き整数を含むすべての基本的なタイプint/int8/int16/int32/int64、符号なし整数uint/uint8/uint16/uint32/uint64、浮動小数点float32/float64、ブールbool、文字列stringなど)、それらのセクション
  • タイプをマップします。キーのためにのみをサポートするstring地図の種類の値に基づいて、。
  • 関数型。

フィールドタイプスライスベース、ベース型と実質的に解決プロセスに対応するのであれば同じです。違いは、同じオプション遭遇スライスタイプのオプションは、値はスライスに追加されるということです。むしろオプション値のスライスタイプよりも最初に表示され表示される値を上書きします。

次の例を見て:

package main

import (
  "fmt"

  "github.com/jessevdk/go-flags"
)

type Option struct {
  IntFlag         int             `short:"i" long:"int" description:"int flag value"`
  IntSlice        []int           `long:"intslice" description:"int slice flag value"`
  BoolFlag        bool            `long:"bool" description:"bool flag value"`
  BoolSlice       []bool          `long:"boolslice" description:"bool slice flag value"`
  FloatFlag       float64         `long:"float", description:"float64 flag value"`
  FloatSlice      []float64       `long:"floatslice" description:"float64 slice flag value"`
  StringFlag      string          `short:"s" long:"string" description:"string flag value"`
  StringSlice     []string        `long:"strslice" description:"string slice flag value"`
  PtrStringSlice  []*string       `long:"pstrslice" description:"slice of pointer of string flag value"`
  Call            func(string)    `long:"call" description:"callback"`
  IntMap          map[string]int  `long:"intmap" description:"A map from string to int"`
}

func main() {
  var opt Option
  opt.Call = func (value string) {
    fmt.Println("in callback: ", value)
  }
  
  err := flags.Parse(&opt, os.Args[1:])
  if err != nil {
    fmt.Println("Parse error:", err)
    return
  }
  
  fmt.Printf("int flag: %v\n", opt.IntFlag)
  fmt.Printf("int slice flag: %v\n", opt.IntSlice)
  fmt.Printf("bool flag: %v\n", opt.BoolFlag)
  fmt.Printf("bool slice flag: %v\n", opt.BoolSlice)
  fmt.Printf("float flag: %v\n", opt.FloatFlag)
  fmt.Printf("float slice flag: %v\n", opt.FloatSlice)
  fmt.Printf("string flag: %v\n", opt.StringFlag)
  fmt.Printf("string slice flag: %v\n", opt.StringSlice)
  fmt.Println("slice of pointer of string flag: ")
  for i := 0; i < len(opt.PtrStringSlice); i++ {
    fmt.Printf("\t%d: %v\n", i, *opt.PtrStringSlice[i])
  }
  fmt.Printf("int map: %v\n", opt.IntMap)
}

ベーシックタイプとそのスライスは比較的簡単ですが、あまりにも多くを導入していません。これはすなわち、上記スライスベース型ポインタ、ことは注目に値するPtrStringSliceフィールドタイプ[]*string
構造は、文字列ポインタに格納されているのでgo-flags、このオプションを解析中に遭遇した文字列を作成し、自動的に、ポインタをセクションに追加されます。

渡して、プログラムを実行します。--pstrsliceオプション:

$ ./main.exe --pstrslice test1 --pstrslice test2
slice of pointer of string flag:
    0: test1
    1: test2

また、当社は、関数型のオプションを定義することができます。唯一の要件は、String型のパラメータの関数です。それぞれの出会いの解析は、この関数を呼び出すためのオプション値パラメータへのオプションとなります。
上記のコードでは、Call関数は単に着信オプション値を出力します。渡して、コードを実行します。--callオプション:

$ ./main.exe --call test1 --call test2
in callback:  test1
in callback:  test2

最後に、go-flagsまた、マップタイプをサポートしていました。キーを制限することでなければならないがstringタイプ、値がプリミティブ型でなければならないだけでなく、より柔軟な構成を実現します。
mapタイプオプションキー値-によって値:のようなパーティションはkey:value、複数設けてもよいです。渡して、コードを実行します。--intmapオプション:

$ ./main.exe --intmap key1:12 --intmap key2:58
int map: map[key1:12 key2:58]

共通設定

go-flags設定オプションの多くを提供し、特定の参照ドキュメントをここでは、2に焦点を当てるrequireddefault

requiredそれは、対応するオプションの値は、それ以外の解析、設定しなければならないことを意味し、空でないErrRequiredエラーを。

defaultデフォルト値を設定するオプション。デフォルト値を設定している場合は、required設定は影響されないかどうか、それは、コマンドライン引数は、このオプションはできませんです。

次の例を参照してください。

package main

import (
  "fmt"
  "log"

  "github.com/jessevdk/go-flags"
)

type Option struct {
  Required    string  `short:"r" long:"required" required:"true"`
  Default     string  `short:"d" long:"default" default:"default"`
}

func main() {
  var opt Option
  _, err := flags.Parse(&opt)
  if err != nil {
    log.Fatal("Parse error:", err)
  }
    
  fmt.Println("required: ", opt.Required)
  fmt.Println("default: ", opt.Default)
}

プログラムを実行し、渡していないdefaultオプション、Defaultフィールドのデフォルト値は、合格しないrequiredオプションを、実行エラーを:

$ ./main.exe -r required-data
required:  required-data
default:  default

$ ./main.exe -d default-data -r required-data
required:  required-data
default:  default-data

$ ./main.exe
the required flag `/r, /required' was not specified
2020/01/09 18:07:39 Parse error:the required flag `/r, /required' was not specified

先進的な機能

オプションは、グループ化されています

package main

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

type Option struct {
  Basic GroupBasicOption `description:"basic type" group:"basic"`
  Slice GroupSliceOption `description:"slice of basic type" group:"slice"`
}

type GroupBasicOption struct {
  IntFlag    int     `short:"i" long:"intflag" description:"int flag"`
  BoolFlag   bool    `short:"b" long:"boolflag" description:"bool flag"`
  FloatFlag  float64 `short:"f" long:"floatflag" description:"float flag"`
  StringFlag string  `short:"s" long:"stringflag" description:"string flag"`
}

type GroupSliceOption struct {
  IntSlice      int         `long:"intslice" description:"int slice"`
  BoolSlice     bool        `long:"boolslice" description:"bool slice"`
  FloatSlice    float64 `long:"floatslice" description:"float slice"`
  StringSlice   string  `long:"stringslice" description:"string slice"`
}

func main() {
  var opt Option
  p := flags.NewParser(&opt, flags.Default)
  _, err := p.ParseArgs(os.Args[1:])
  if err != nil {
    log.Fatal("Parse error:", err)
  }
    
  basicGroup := p.Command.Group.Find("basic")
  for _, option := range basicGroup.Options() {
    fmt.Printf("name:%s value:%v\n", option.LongNameWithNamespace(), option.Value())
  }
    
  sliceGroup := p.Command.Group.Find("slice")
  for _, option := range sliceGroup.Options() {
    fmt.Printf("name:%s value:%v\n", option.LongNameWithNamespace(), option.Value())
  }
}

基本的なコードの我々のスライスタイプと二つの構造を分割するそのタイプのオプション上記のように、このコードは、特に大量のコードの場合には、シャープでより自然に見えるようにすることができます。
これも利点があり、我々は、使用しようとする--helpプログラムを実行します:

$ ./main.exe --help
Usage:
  D:\code\golang\src\github.com\darjun\go-daily-lib\go-flags\group\main.exe [OPTIONS]

basic:
  /i, /intflag:      int flag
  /b, /boolflag      bool flag
  /f, /floatflag:    float flag
  /s, /stringflag:   string flag

slice:
  /intslice:     int slice
  /boolslice     bool slice
  /floatslice:   float slice
  /stringslice:  string slice

Help Options:
  /?                 Show this help message
  /h, /help          Show this help message

ヘルプ出力は、パケットが見やすいようにショーの私達のセットに従ったものです。

サブコマンド

go-flags子供の養育費の受注。我々は、多くの場合、コマンドラインプログラムGitの移動を使用して、サブコマンドの数が多いです。たとえばgo versiongo buildgo rungit statusgit commitこれらのコマンドは、version/build/run/status/commit息子のコマンドです。
使用するgo-flagsサブコマンドの定義は簡単です:

package main

import (
  "errors"
  "fmt"
  "log"
  "strconv"
  "strings"

  "github.com/jessevdk/go-flags"
)

type MathCommand struct {
  Op string `long:"op" description:"operation to execute"`
  Args []string
  Result int64
}

func (this *MathCommand) Execute(args []string) error {
  if this.Op != "+" && this.Op != "-" && this.Op != "x" && this.Op != "/" {
    return errors.New("invalid op")
  }

  for _, arg := range args {
    num, err := strconv.ParseInt(arg, 10, 64)
    if err != nil {
      return err
    }

    this.Result += num
  }

  this.Args = args
  return nil
}

type Option struct {
    Math MathCommand `command:"math"`
}

func main() {
    var opt Option
    _, err := flags.Parse(&opt)

    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("The result of %s is %d", strings.Join(opt.Math.Args, opt.Math.Op), opt.Math.Result)
}

サブコマンドを実装する必要がgo-flags定義されたCommanderインタフェースを:

type Commander interface {
    Execute(args []string) error
}

彼らはしていない場合は、コマンドラインの解析---パラメータが始まり、go-flagsそれはサブコマンド名としてそれを解釈しようとします。ラベルの構造使用して、サブコマンドの名前command指定を。
サブコマンドのパラメータは、パラメータのサブコマンドとして戻ってくる、サブコマンドもオプションを持つことができます。

上記のコードでは、我々は、乗算、除算サブコマンドを減算し、算出した任意の整数の追加を達成することができますmath

そして、あなたはどのように使用できるかを見てみましょう:

$ ./main.exe math --op + 1 2 3 4 5
The result of 1+2+3+4+5 is 15

$ ./main.exe math --op - 1 2 3 4 5
The result of 1-2-3-4-5 is -13

$ ./main.exe math --op x 1 2 3 4 5
The result of 1x2x3x4x5 is 120

$ ./main.exe math --op ÷ 120 2 3 4 5
The result of 120÷2÷3÷4÷5 is 1

乗算記号を使用していない、という注意*と除算記号を/、彼らは認識できません。

他の

go-flagsライブラリは、Windowsのフォーマットオプション(のサポートなど、多くの興味深い機能がある/v/verbose)、環境変数からデフォルト値を読み取るiniファイルからデフォルトの設定を読んで、というように。私たちは、自分の研究に行くことができます興味を持っています-

参照

  1. フラグ・ゴーのGithubリポジトリ
  2. フラグ-囲碁 godocドキュメント

私のブログ

私は〜一緒に学び、一緒に進行、GoUpUp []パブリックマイクロチャンネル番号の関心を歓迎します

ブログ記事複数のプラットフォームからこの記事OpenWriteリリース!

おすすめ

転載: www.cnblogs.com/darjun/p/12189459.html
おすすめ