cobra
の中のフラグの実装はspf13/pflagという cobra
と同じ方が作られている別のライブラリが使われています。このライブラリは標準の flag
パッケージと似ているので、使ったことある方は使用感に違和感は感じないかと思います。
以下の記事で作った簡単なコマンドラインツールを元にフラグを追加していきます。 simple-minds-think-alike.hatenablog.com
前提
以下のバージョンで確認しています。
- go: v1.14.13
- spf13/cobra: v1.1.1
- spf13/pflag: v1.0.5
フラグの分類
フラグは以下の2つに分類されます。
今回は、ローカルフラグを使ってルートコマンドに--name
という文字列型のフラグを追加してみます。
フラグの追加
ルートコマンドcmd/root.go
の2箇所に処理を追加します。
package cmd import ( "fmt" "github.com/spf13/cobra" "os" ) var rootCmd = &cobra.Command{ Use: "helloWorldApp", Short: "A brief description of your application", Long: `A longer description that spans multiple lines and likely contains examples and usage of using your application.`, Run: func(cmd *cobra.Command, args []string) { // ②CLIを実際の処理 (Run()関数内) でフラグを参照 // nameフラグが渡されていればそれを表示 name, _ := cmd.Flags().GetString("name") if name != "" { fmt.Printf("hello world! - %s san!\n", name) } else { fmt.Println("hello world!") } }, } func Execute() { if err := rootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(1) } } func init() { // ①CLIを初期化する処理(init()内)でフラグを定義 // 第1引数: フラグ名、第2引数: 省略したフラグ名 // 第3引数: デフォルト値、第4引数: フラグの説明 rootCmd.Flags().StringP("name", "n", "", "Your name") }
実行
追加したフラグを指定する場合と指定しない両方の場合で、コマンドを実行してみます。
# フラグを指定しないで実行した場合 $ go run main.go hello world! # フラグを指定した場合 $ go run main.go --name pikotaro hello world! - pikotaro san! # 省略した名前でフラグを指定した場合 $ go run main.go -n pikotaro hello world! - pikotaro san!
name
フラグを指定した場合のみ名前が出力されていて、フラグの有無でプログラムの挙動が変わることを確認できました。
ヘルプを確認
また、ヘルプを表示すると Flags
の箇所に追加したフラグに関する記述が追加される事も確認できます。
$ go run main.go -h Usage: helloWorldApp [flags] helloWorldApp [command] Available Commands: calc A brief description of your command help Help about any command Flags: -h, --help help for helloWorldApp -n, --name string Your name
また、ルートコマンドにローカルフラグを追加したため、 calc
サブコマンドにはフラグは追加されていません。
$ go run main.go calc -h Usage: helloWorldApp calc [flags] Flags: -h, --help help for calc
別の方法でフラグを追加する
Command.StringP() 関数で、文字列のフラグを追加できましたが、他にもフラグを追加する方法があります。
省略したフラグ名なしでフラグを追加
Command.String() 関数を使うと省略したフラグ名なしでフラグを追加できます。
// 第1引数: フラグ名、第2引数: デフォルト値、第3引数: フラグの説明 cmd.Flags().String("name", "", "Your name")
ヘルプを表示すると以下のように表示され、省略した名前ではフラグを指定できなくなっています。
Flags: -h, --help help for helloWorldApp --name string Your name
変数を指定してフラグを追加
Command.StringVarP()、 Command.StringVar() 関数を指定すると変数を指定してフラグを追加できます。
変数を指定することで、 cmd.Flags().GetString("name")
のようにフラグの値を取得するための処理を書かなくても、値を参照できます。
StringVarP
は省略したフラグ名を指定する関数、 StringVar
は省略したフラグ名を指定しない関数です。
// 文字列型の変数を定義 var name string // 第1引数: 変数ポインタ、第2引数: フラグ名、、第3引数: 省略したフラグ名 // 第4引数: デフォルト値、第5引数: フラグの説明 cmd.Flags().StringVarP(&name, "name", "n", "", "Your name") // 第1引数: 変数ポインタ、第2引数: フラグ名 // 第3引数: デフォルト値、第4引数: フラグの説明 cmd.Flags().StringVar(&name, "name", "", "Your name") // フラグnameの値を標準出力 fmt.Println(name)
図にまとめてみると
それぞれの関数は以下のような位置づけになります。
別の種類のフラグを追加する
ここまでが文字列型のフラグの追加方法の共有ですが、同様の方法で他の型のフラグを追加できます。Bool や Int のような基本的な型の他にCountや IP、Duration といった様々な型のフラグを追加可能です。