cobra几乎是每个学习golang的码农必备的技能,简要来说,他是个编写命令行的工具,在大型项目中经常使用cobra来启动服务,接下来直接上代码
root.go
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var Verbose bool
var Author string
var Author2 string
var Author3 string
var Test bool
var rootCmd = &cobra.Command{
Use: "hugo",
Short: "Hugo is a very fast static site generator",
Args: cobra.NoArgs,
// NoArgs - the command will report an error if there are any positional args.
// ArbitraryArgs - the command will accept any args.
// OnlyValidArgs - the command will report an error if there are any positional args that are not in the ValidArgs field of Command.
// MinimumNArgs(int) - the command will report an error if there are not at least N positional args.
// MaximumNArgs(int) - the command will report an error if there are more than N positional args.
// ExactArgs(int) - the command will report an error if there are not exactly N positional args.
// ExactValidArgs(int) = the command will report and error if there are not exactly N positional args OR if there are any positional args that are not in the ValidArgs field of Command
// RangeArgs(min, max) - the command will report an error if the number of args is not between the minimum and maximum number of expected args.
// Args match a function ,so you can difine your own function
Long: `A Fast and Flexible Static Site Generator built with
love by spf13 and friends in Go.
Complete documentation is available at http://hugo.spf13.com`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("main root")
fmt.Println(cmd.Flags().GetString("author"))
fmt.Println(viper.Get("author"))
fmt.Println(cmd.Flags().GetBool("test"))
// Do Stuff Here
},
// PersistentPreRun
// PreRun
// Run
// PostRun
// PersistentPostRun
/**
以上key按顺序执行对应的函数,而Persistent代表始终执行,并且对于子命令也一样,如果子命令没有定义Persistent
的key的话,则执行父命令的Persistent*Run函数。
**/
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func init() {
cobra.OnInitialize(initConfig) //这会在运行每个子命令之前运行,后面无法更新viper中初始config的数据
rootCmd.PersistentFlags().StringVarP(&Author, "author", "a", "defaultAuthor", "作者名")
rootCmd.PersistentFlags().StringVar(&Author2, "author2", "defaultAuthor2", "作者名2")
rootCmd.PersistentFlags().String("author3", "defaultAuthor3", "作者名3")
/**
方法名带P的则代表可在参数中添加短声明,带有Var的则代表可以将值绑定到变量中
**/
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
// 将用户输入的author信息绑定到viper缓存中,优先级低于viper本身从配置信息中读取的绑定
rootCmd.Flags().BoolVarP(&Test, "test", "t", false, "test")
// PersistentFlags为全局Flag,不带Persistent的为本地Flag
viper.BindPFlag("author", rootCmd.Flags().Lookup("test"))
// 绑定局部Flag
rootCmd.MarkPersistentFlagRequired("author")
rootCmd.MarkFlagRequired("author2")
rootCmd.MarkPersistentFlagRequired("author3") // 仅对于全局Flag生效,标记其为必须输入的Flag
rootCmd.MarkFlagRequired("test") // 仅对于局部Flag生效,标记其为必须输入的Flag
}
func initConfig() {
viper.AddConfigPath("./")
viper.AddConfigPath("./conf")
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AutomaticEnv()
if err := viper.ReadInConfig(); err != nil {
fmt.Println("Error:", err)
os.Exit(1)
}
}
version.go
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version number of Hugo",
TraverseChildren: true,
// 用途不明
Long: `All software has versions. This is Hugo's`,
Args: cobra.MaximumNArgs(5),
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Hugo Static Site Generator v0.9 -- HEAD")
fmt.Println(cmd.Flags().GetString("name"))
fmt.Println(cmd.Flags().GetString("author"))
fmt.Println(args)
},
}
func init() {
rootCmd.AddCommand(versionCmd)
var Source string
versionCmd.Flags().StringVarP(&Source, "source", "s", "", "读取文件路径")
var Name string
versionCmd.Flags().StringVarP(&Name, "name", "n", "default name", "你的名字")
// rootCmd.SetArgs([]string{"version", "second-arg", "third-arg"})
/**
此命令可以设置全局初始参数,大概用于测试?例如此参数设置后可以直接进入version的子命令并添加两个参数
**/
}
最后在main.go中执行root.go的Execute函数即可,注意init函数将会在程序执行之前执行来进行初始化,具体请参考另一篇博客关于init函数的介绍,关于viper的使用请参考viper的使用介绍