go常用命令行包使用汇总 flag, pflag, viper, corba
flag用法 flag使用几种方式
flag.Xxx, 其中 Xxx 可以是 Int、String 等;返回一个相应类型的指针
flag.XxxVar,其中 XxxVar 可以是 Int、String 等;将 flag 绑定到一个变量上
自定义类型flag.Var解析. 自定义类型需要实现flag.Value接口中的方法 Set 和String
flagset生成子命令
//解析 flag 通过以上几种方法定义好命令行flag参数后,需要通过调用flag.Parse()来对命令行参数进行解析。
支持的命令行参数格式有以下几种:
-flag xxx (使用空格,一个-符号) –flag xxx (使用空格,两个-符号) -flag=xxx (使用等号,一个-符号) –flag=xxx (使用等号,两个-符号) 其中,布尔类型的参数必须使用等号的方式指定。bool类型如果flag出现就为true,否则为默认值,只能使用=号连接 Flag解析在第一个非flag参数(单个”-“不是flag参数)之前停止,或者在终止符”–“之后停止。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 package mainimport ( "flag" "fmt" "strings" "time" ) type interval []time.Durationfunc (i *interval) String() string { return fmt.Sprint(*i) } func (i *interval) Set(value string ) error { for _, dt := range strings.Split(value, "," ) { duration, err := time.ParseDuration(dt) if err != nil { return err } *i = append (*i, duration) } return nil } func main () { wordPtr := flag.String("word" , "test" , "word" ) durtion := flag.Duration("duration" , time.Minute, "set time duration" ) var svar string flag.StringVar(&svar, "svar" , "bar" , "a string var" ) var i interval flag.Var(&i, "interval" , "解析url" ) flag.Parse() fmt.Println("word:" , *wordPtr) fmt.Println("stringval:" , svar) fmt.Println("durtion:" , *durtion) fmt.Println("custom:" , i) }
flagset 子命令方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package mainimport ( "flag" "fmt" "os" ) func main () { sub := flag.NewFlagSet("sub1" , flag.ExitOnError) intervals := sub.String("interval" , "1m" , "sub interval" ) nums := sub.Int("num" , 3 , "sub nums" ) bools := sub.Bool("bool" , true , "sub nums" ) sub.Parse(os.Args[2 :]) fmt.Println(*intervals) fmt.Println(*nums) fmt.Println(*bools) }
pflag用法 pflag是flag的增强版,兼容flag,同时有自己新增的一些特性。
pflag使用几种方式
pflag. 类方法名会将标志参数值存储在指针中并返回。
pflag.Var 类方法名中包含 Var 关键字的,会将标志参数值绑定到第一个指针类型的参数。
pflag.P、pflag.VarP 类方法名以 P 结尾的,支持简短标志。 一个完整标志在命令行传参时使用的分界符为 –,而一个简短标志的分界符则为 -。
pflag中flag定义以及Value接口定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 type Flag struct { Name string Shorthand string Usage string Value Value DefValue string Changed bool NoOptDefVal string Deprecated string Hidden bool ShorthandDeprecated string Annotations map [string ][]string } type Value interface { String() string Set(string ) error Type() string }
pflag应用代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 package mainimport ( "fmt" "strings" "time" "github.com/spf13/pflag" ) type intervals []time.Durationfunc (i *intervals) String() string { return fmt.Sprint(*i) } func (i *intervals) Set(value string ) error { for _, dt := range strings.Split(value, "," ) { duration, err := time.ParseDuration(dt) if err != nil { return err } *i = append (*i, duration) } return nil } func (i *intervals) Type() string { return "intervals" } func main () { pflagxxx := pflag.String("pflagxxx" , "pflagxxx" , "string for args to return a string pointer" ) var pflagxxxVar string pflag.StringVar(&pflagxxxVar, "pflagxxxVar" , "pflagxxxVar" , "stringvar for args to var" ) pflagxxxP := pflag.StringP("pflagxxxP" , "t" , "pflagxxxP" , "string for args to return a string pointer with shorthand" ) var pflagxxxVarP string pflag.StringVarP(&pflagxxxVarP, "pflagxxxVarP" , "p" , "pflagxxxVarP" , "stringvar for args to var with shorthand" ) var in intervals pflag.Var(&in, "interval" , "间隔" ) var inp intervals pflag.VarP(&inp, "intervalp" , "i" , "简短标志间隔" ) pflag.Lookup("interval" ).NoOptDefVal = "2m" pflag.CommandLine.SortFlags = false pflag.Parse() fmt.Println(*pflagxxx) fmt.Println(pflagxxxVar) fmt.Println(*pflagxxxP) fmt.Println(pflagxxxVarP) fmt.Println(in) fmt.Println(inp) fmt.Printf("NFlag: %v\n" , pflag.NFlag()) fmt.Printf("NArg: %v\n" , pflag.NArg()) fmt.Printf("Args: %v\n" , pflag.Args()) fmt.Printf("Arg(1): %v\n" , pflag.Arg(1 )) }
viper用法 Viper是Go应用程序现代化的、完整的解决方案,能够处理不同格式的配置文件,让我们在构建现代应用程序时,不必担心配置文件格式。Viper也能够满足我们对应用配置的各种需求。
Viper可以从不同的位置读取配置,不同位置的配置具有不同的优先级,高优先级的配置会覆盖低优先级相同的配置,按优先级从高到低排列如下:
通过viper.Set函数显示设置的配置
命令行参数
环境变量
配置文件
Key/Value存储
默认值
这里需要注意,Viper配置键不区分大小写。
Viper有很多功能,最重要的两类功能是读入配置和读取配置。读入配置 读入配置,就是将配置读入到Viper中,有如下读入方式:
设置默认的配置文件名。
读取配置文件。
监听和重新读取配置文件。
从io.Reader读取配置。
从环境变量读取。
从命令行标志读取。
从远程Key/Value存储读取。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 package mainimport ( "crypto/md5" "encoding/hex" "fmt" "github.com/fsnotify/fsnotify" "github.com/spf13/pflag" "github.com/spf13/viper" _ "github.com/spf13/viper/remote" "io/ioutil" "time" ) var ( confMD5 string username = pflag.StringP("username" , "u" , "pflag-username" , "help message for username" ) ) func main () { pflag.Parse() viper.AddRemoteProvider("consul" , "172.20.6.37:8500" , "user" ) viper.SetConfigType("YAML" ) if err := viper.ReadRemoteConfig(); err != nil { fmt.Printf("-=============%s" , err.Error()) } viper.SetDefault("projectbase" , "prevalue" ) fmt.Printf("+++++%v\n" , viper.Get("projectbase" )) viper.OnConfigChange(func (e fsnotify.Event) { tconfMD5, _ := ReadFileMd5("top.yaml" ) fmt.Printf("[%+v]\n" , tconfMD5) if tconfMD5 == confMD5 { return } confMD5 = tconfMD5 fmt.Println("cfg start...." , e.String(), e.Name) }) viper.WatchConfig() var topcfg TopCfg err := viper.Unmarshal(&topcfg) if err != nil { return } fmt.Printf("%+v\n" , topcfg) fmt.Printf("%#v\n===" , topcfg) if keys := viper.AllKeys(); len (keys) > 0 { for _, key := range keys { fmt.Printf("%s:%v\n" , key, viper.Get(key)) } } grpcCfg := viper.Sub("grpc" ) fmt.Printf("%v\n" , grpcCfg.AllKeys()) fmt.Printf("%v\n" , grpcCfg.Get("username" )) fmt.Printf("%v\n" , viper.Get("grpc.username" )) viper.WriteConfigAs("new.yaml" ) for { time.Sleep(3 * time.Second) fmt.Printf("%v\n" , viper.Get("projectbase" )) } } func ReadFileMd5 (sfile string ) (string , error ) { ssconfig, err := ioutil.ReadFile(sfile) if err != nil { return "" , err } return GetMD5(ssconfig), nil } func GetMD5 (s []byte ) string { m := md5.New() m.Write([]byte (s)) return hex.EncodeToString(m.Sum(nil )) }
corba用法 Cobra 是一个 Go 语言开发的命令行(CLI)框架,它提供了简洁、灵活且强大的方式来创建命令行程序。它包含一个用于创建命令行程序的库(Cobra 库),以及一个用于快速生成基于 Cobra 库的命令行程序工具(Cobra 命令)。Cobra 是由 Go 团队成员 spf13 为 Hugo 项目创建的,并已被许多流行的 Go 项目所采用,如 Kubernetes、Helm、Docker (distribution)、Etcd 等。
参考 Go - flag:命令行flags解析 Go 命令行参数解析工具 pflag 使用 在 Go 中如何使用 Viper 来管理配置 Go 语言现代命令行框架 Cobra 详解