安装:go get -u github.com/spf13/cobra/cobra
cobra是一个用于生成命令行程序的库,下面简单介绍一下用法,具体可以参考文档
创建命令:
//打印命令
var cmdPrint = &cobra.Command{
Use: "print [string to print]", //命令名是print
Short: "Print anything to the screen", //该命令的简短说明
Long: `print is for printing anything back to the screen.
For many years people have printed back to the screen.`, //该命令的详细说明
Args: cobra.MinimumNArgs(1), //指定该命令最少要有一个参数
Run: func(cmd *cobra.Command, args []string) { //该命令执行的函数
fmt.Println("Print: " + strings.Join(args, " "))
},
}
//回显命令
var cmdEcho = &cobra.Command{
Use: "echo [string to echo]",
Short: "Echo anything to the screen",
Long: `echo is for echoing anything back.
Echo works a lot like print, except it has a child command.`,
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Print: " + strings.Join(args, " "))
},
}
//指定回显次数
var cmdTimes = &cobra.Command{
Use: "times [# times] [string to echo]",
Short: "Echo anything to the screen more times",
Long: `echo things multiple times back to the user by providing
a count and a string.`,
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
for i := 0; i < echoTimes; i++ {
fmt.Println("Echo: " + strings.Join(args, " "))
}
},
}
还可以给命令加Flag
Flag又分为Local Flag和Persistent Flag
区别就是Local Flag只用于本条命令,而Persistent Flag还可以用于子命令
实际中常常将flag和viper绑定viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
rootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
//cmdTimes.Flags().IntVar(&echoTimes, "times", 1, "times to echo the input") //与下面这条命令的区别就是这里不能指定短flag
cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input") //flag绑定的值,长flag,短flag, 默认值,说明
cmdTimes.MarkFlagRequired("times") //将times设置为必须说明的flag,不说明会报错
添加子命令:命令本身不分等级,下面人为设置了子命令
var rootCmd = &cobra.Command{Use: "app"} //创建一个根命令
rootCmd.AddCommand(cmdPrint, cmdEcho) //添加子命令
cmdEcho.AddCommand(cmdTimes) //添加子命令
运行命令:
rootCmd.Execute() //运行命令
每条命令按顺序执行的函数:
默认情况下命令输错且编辑距离不大于2时会智能提示,可用下面这条代码修改默认值。
command.SuggestionsMinimumDistance = 1
还可以关闭智能提示command.DisableSuggestions = true
viper用来读取环境变量,可以是命令行提供的,也可以是各种配置文件提供的,可以在不重启服务的情况下动态设置新的配置项的值并使之实时生效。
设置默认值:
viper.SetDefault("ContentDir", "content")
viper.SetDefault("LayoutDir", "layouts")
viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})
读取配置文件:
viper.SetConfigName("config") // name of config file (without extension)
viper.AddConfigPath("/etc/appname/") // path to look for the config file in
viper.AddConfigPath("$HOME/.appname") // call multiple times to add many search paths
viper.AddConfigPath(".") // optionally look for config in the working directory
err := viper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
监视配置文件的变化:
viper.WatchConfig() //调用这个函数之前一定要确保已经加入了所有的查找路径
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
})
重新设置环境变量,覆盖:
viper.Set("Verbose", true)
viper.Set("LogFile", LogFile)
取别名:
viper.RegisterAlias("loud", "Verbose")
viper.Set("verbose", true) // same result as next line
viper.Set("loud", true) // same result as prior line
viper.GetBool("loud") // true
viper.GetBool("verbose") // true
还可以从io.Reader
读取配置:
viper.SetConfigType("yaml") // or viper.SetConfigType("YAML")
// any approach to require this configuration into your program.
var yamlExample = []byte(`
Hacker: true
name: steve
hobbies:
- skateboarding
- snowboarding
- go
clothing:
jacket: leather
trousers: denim
age: 35
eyes : brown
beard: true
`)
viper.ReadConfig(bytes.NewBuffer(yamlExample))
viper.Get("name") // this would be "steve"
从viper中取值:
需要注意的是,如果没有设置过该值,会返回对应类型的零值。
如果要判断是否设置过,用IsSet()
。
Get(key string) : interface{}
GetBool(key string) : bool
GetFloat64(key string) : float64
GetInt(key string) : int
GetString(key string) : string
GetStringMap(key string) : map[string]interface{}
GetStringMapString(key string) : map[string]string
GetStringSlice(key string) : []string
GetTime(key string) : time.Time
GetDuration(key string) : time.Duration
IsSet(key string) : bool
AllSettings() : map[string]interface{}
安装:go get github.com/op/go-logging
下面是github上的样例,具体可以查询文档
package main
import (
"os"
"github.com/op/go-logging"
)
var log = logging.MustGetLogger("example") //创建一个名为example的日志对象log
// Example format string. Everything except the message has a custom color
// which is dependent on the log level. Many fields have a custom output
// formatting too, eg. the time returns the hour down to the milli second.
var format = logging.MustStringFormatter( //输出格式
`%{color}%{time:15:04:05.000} %{shortfunc} ▶ %{level:.4s} %{id:03x}%{color:reset} %{message}`,
)
// Password is just an example type implementing the Redactor interface. Any
// time this is logged, the Redacted() function will be called.
type Password string
func (p Password) Redacted() interface{} {
return logging.Redact(string(p))
}
func main() {
// For demo purposes, create two backend for os.Stderr.
backend1 := logging.NewLogBackend(os.Stderr, "", 0) //创建日志输出对象,此处是标准错误输出,前缀是""
backend2 := logging.NewLogBackend(os.Stderr, "", 0)
// For messages written to backend2 we want to add some additional
// information to the output, including the used log level and the name of
// the function.
backend2Formatter := logging.NewBackendFormatter(backend2, format) //将输出对象与输出格式绑定
// Only errors and more severe messages should be sent to backend1
backend1Leveled := logging.AddModuleLevel(backend1)
backend1Leveled.SetLevel(logging.ERROR, "") //只有大于error级别的才输出到这里
// Set the backends to be used.
logging.SetBackend(backend1Leveled, backend2Formatter) //设置日志的输出对象
log.Debugf("debug %s", Password("secret"))
log.Info("info")
log.Notice("notice")
log.Warning("warning")
log.Error("err")
log.Critical("crit")
}
安装:go get github.com/syndtr/goleveldb/leveldb
查询文档
打开数据库:
db, err := leveldb.OpenFile("path/to/db", nil)
defer db.Close()
查询、插入、删除:
// Remember that the contents of the returned slice should not be modified.
data, err := db.Get([]byte("key"), nil)
err = db.Put([]byte("key"), []byte("value"), nil)
err = db.Delete([]byte("key"), nil)
遍历:
iter := db.NewIterator(nil, nil)
for iter.Next() {
// Remember that the contents of the returned slice should not be modified, and
// only valid until the next call to Next.
key := iter.Key()
value := iter.Value()
...
}
iter.Release()
err = iter.Error()
遍历指定值:
iter := db.NewIterator(nil, nil)
for ok := iter.Seek(key); ok; ok = iter.Next() {
// Use key/value.
}
iter.Release()
err = iter.Error()