cobra
Cobra既是用于创建强大的现代CLI应用程序的库,也是用于生成应用程序和命令文件的程序。许多使用最广泛的Go项目都是使用Cobra构建的
Cobra是建立在结构的命令、参数和标志之上。命令(Commands)代表操作,参数(Args)和标志(Flags)是这些行动的修饰符。最好的应用程序就像读取句子。用户会知道如何使用本机应用程序,因为他们将理解如何使用它。
要遵循的模式是
APPNAME VERB NOUN --ADJECTIVE
或
APPNAME COMMAND ARG --FLAG
在创建 cobra 应用前需要先安装 cobra 包: $ go get -u github.com/spf13/cobra/cobra 然后就可以用 cobra 程序生成应用程序框架了: cts@cts-pc:~/test/go/src/github.com/spf13$ cobra init demo --pkg-name=github.com/spf13/demo cts@cts-pc:~/test/go/src/github.com/spf13$ go build cts@cts-pc:~/test/go/src/github.com/spf13/demo$ ./demo A longer description that spans multiple lines and likely contains examples and usage of using your application. For example: Cobra is a CLI library for Go that empowers applications. This application is a tool to generate the needed files to quickly create a Cobra application. cts@cts-pc:~/test/go/src/github.com/spf13/demo$ tree . ├── cmd │ └── root.go ├── demo └── main.go
自动生成的代码如下
//main.go package main import "github.com/spf13/demo/cmd" func main() { cmd.Execute() }
//root.go package cmd import ( "fmt" "github.com/spf13/cobra" "os" homedir "github.com/mitchellh/go-homedir" "github.com/spf13/viper" ) var cfgFile string // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "demo", 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. For example: Cobra is a CLI library for Go that empowers applications. This application is a tool to generate the needed files to quickly create a Cobra application.`, // Uncomment the following line if your bare application // has an action associated with it: // Run: func(cmd *cobra.Command, args []string) { }, } // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { if err := rootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(1) } } func init() { cobra.OnInitialize(initConfig) rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.demo.yaml)") rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") } // initConfig reads in config file and ENV variables if set. func initConfig() { if cfgFile != "" { // Use config file from the flag. viper.SetConfigFile(cfgFile) } else { // Find home directory. home, err := homedir.Dir() if err != nil { fmt.Println(err) os.Exit(1) } // Search config in home directory with name ".demo" (without extension). viper.AddConfigPath(home) viper.SetConfigName(".demo") } viper.AutomaticEnv() // read in environment variables that match // If a config file is found, read it in. if err := viper.ReadInConfig(); err == nil { fmt.Println("Using config file:", viper.ConfigFileUsed()) } }
rootCmd是根命令
给根命令添加子命令
cts@cts-pc:~/test/go/src/github.com/spf13/demo$ cobra add version version created at /home/cts/test/go/src/github.com/spf13/demo cts@cts-pc:~/test/go/src/github.com/spf13/demo$ go build cts@cts-pc:~/test/go/src/github.com/spf13/demo$ ./demo version version called cts@cts-pc:~/test/go/src/github.com/spf13/demo$ tree . ├── cmd │ ├── root.go │ └── version.go ├── demo └── main.go 1 directory, 4 files
//version.go package cmd import ( "fmt" "github.com/spf13/cobra" ) // versionCmd represents the version command var versionCmd = &cobra.Command{ Use: "version", Short: "A brief description of your command", Long: `A longer description that spans multiple lines and likely contains examples and usage of using your command. For example: Cobra is a CLI library for Go that empowers applications. This application is a tool to generate the needed files to quickly create a Cobra application.`, Run: func(cmd *cobra.Command, args []string) { fmt.Println("version called") }, } func init() { rootCmd.AddCommand(versionCmd) }
给version命令添加子命令
cts@cts-pc:~/test/go/src/github.com/spf13/demo$ cobra add help help created at /home/cts/test/go/src/github.com/spf13/demo . ├── cmd │ ├── help.go │ ├── root.go │ └── version.go ├── demo └── main.go 1 directory, 5 files
修改自动生成的help.go
package cmd import ( "fmt" "github.com/spf13/cobra" ) // helpCmd represents the help command var helpCmd = &cobra.Command{ Use: "help", Short: "A brief description of your command", Long: `A longer description that spans multiple lines and likely contains examples and usage of using your command. For example: Cobra is a CLI library for Go that empowers applications. This application is a tool to generate the needed files to quickly create a Cobra application.`, Run: func(cmd *cobra.Command, args []string) { fmt.Println("help called") }, } func init() { //rootCmd.AddCommand(helpCmd) versionCmd.AddCommand(helpCmd) }
继续编译和运行
cts@cts-pc:~/test/go/src/github.com/spf13/demo$ vi cmd/help.go //修改rootCmd为versionCmd cts@cts-pc:~/test/go/src/github.com/spf13/demo$ go build cts@cts-pc:~/test/go/src/github.com/spf13/demo$ ./demo version help help called
为Command添加选项(flags)
选项(flags)用来控制 Command 的具体行为。根据选项的作用范围,可以把选项分为persistent和local两类:
Persistent Flags:全局性flag, 可用于它所分配的命令以及该命令下的每个命令。在根上分配标志作为全局flag。
Local Flags:局部性flag,在本args分配一个标志,该标志仅适用于该命令。
Required flags:必选flag,flag默认是可选的。如果希望命令在未设置flag时报告错误,请将其标记为required。
修改version.go的init()函数,添加一个全局flag,一个局部flag
func init() { rootCmd.AddCommand(versionCmd) versionCmd.PersistentFlags().String("global_version", "", "A help for foo") versionCmd.Flags().BoolP("local_version", "t", false, "Help message for toggle") }
测试结果
cts@cts-pc:~/test/go/src/github.com/spf13/demo$ ./demo version -h A longer description that spans multiple lines and likely contains examples and usage of using your command. For example: Cobra is a CLI library for Go that empowers applications. This application is a tool to generate the needed files to quickly create a Cobra application. Usage: demo version [flags] demo version [command] Available Commands: help A brief description of your command Flags: --global_version string A help for foo -h, --help help for version -t, --local_version Help message for toggle Global Flags: --config string config file (default is $HOME/.demo.yaml) Use "demo version [command] --help" for more information about a command. cts@cts-pc:~/test/go/src/github.com/spf13/demo$ cts@cts-pc:~/test/go/src/github.com/spf13/demo$ cts@cts-pc:~/test/go/src/github.com/spf13/demo$ ./demo version help -h A longer description that spans multiple lines and likely contains examples and usage of using your command. For example: Cobra is a CLI library for Go that empowers applications. This application is a tool to generate the needed files to quickly create a Cobra application. Usage: demo version help [flags] Flags: -h, --help help for help Global Flags: --config string config file (default is $HOME/.demo.yaml) --global_version string A help for foo
version和help命令都继承了root命令的--config,help继承了version的--global_version。由此可见子命令可以继承父命令的全局选项。
version有--local_version,而help没有。说明局部选项不可继承。