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没有。说明局部选项不可继承。

posted @ 2021-02-02 15:29  牧 天  阅读(388)  评论(0)    收藏  举报