github.com/chain5j/chain5j-pkg@v1.0.7/cli/cli.go (about) 1 // Package cli 2 // 3 // @author: xwc1125 4 package cli 5 6 import ( 7 "fmt" 8 "path/filepath" 9 10 "github.com/fsnotify/fsnotify" 11 "github.com/spf13/cobra" 12 "github.com/spf13/pflag" 13 "github.com/spf13/viper" 14 ) 15 16 type Command *cobra.Command 17 18 // Cli cobra 在使用中,如果执行过中任何的Run或RunE没有执行过,那么cobra.OnInitialize(func func1) 19 // 中的func1 就不会执行 20 type Cli struct { 21 appInfo *AppInfo 22 rootCmd *cobra.Command 23 viper *viper.Viper 24 25 subCmds []Command 26 27 readConfigFunc func(viper *viper.Viper) 28 configFile string 29 configEnv string 30 } 31 32 // NewCli 创建新的命令对象 33 func NewCli(a *AppInfo) *Cli { 34 return NewCliWithViper(a, nil) 35 } 36 37 // NewCliWithViper 添加viper创建新的命令对象 38 func NewCliWithViper(a *AppInfo, _viper *viper.Viper) *Cli { 39 if _viper == nil { 40 _viper = viper.New() 41 } 42 rootCmd := &cobra.Command{ 43 Use: a.App, 44 Version: a.Version, 45 Run: func(cmd *cobra.Command, args []string) { 46 fmt.Println(a.Welcome) 47 }, 48 } 49 return &Cli{ 50 appInfo: a, 51 rootCmd: rootCmd, 52 viper: _viper, 53 subCmds: make([]Command, 0), 54 } 55 } 56 57 // InitFlags 初始化flag 58 // viper 按照如下顺序查找flag key: 59 // - pflag里面的被命令行显式设置的key 60 // - 环境变量显式设置的 61 // - 配置文件显式设置的 62 // - KV存储的 63 // - 通过viper设置的default flag 64 // - 如果前面都没有变化,最后使用pflag的默认值 65 // 66 // 所以在Unmarshal的时候命令行里面显式设置的flag会覆盖配置文件里面的flag 67 // 如果配置文件没有这个flag,会用pflag的默认值 68 // @params useDefaultFlags 是否使用默认的flag:config,env 69 // @params flagSetFunc flag设置的回调函数,函数中为viper及rootFlags 70 // @params readConfigFunc 读取配置的回调函数 71 func (cli *Cli) InitFlags(useDefaultFlags bool, flagSetFunc func(rootFlags *pflag.FlagSet), readConfigFunc func(viper *viper.Viper)) (err error) { 72 // 获取当前命令行 73 { 74 rootFlags := cli.rootCmd.PersistentFlags() 75 if useDefaultFlags { 76 rootFlags.StringVar(&cli.configFile, "config", "./conf/config.yaml", "config file (default is ./conf/config.yaml)") 77 rootFlags.StringVar(&cli.configEnv, "env", "", "config env") 78 } 79 if flagSetFunc != nil { 80 flagSetFunc(rootFlags) 81 } 82 // 将完整的命令绑定到viper上 83 if err := cli.viper.BindPFlags(rootFlags); err != nil { 84 return err 85 } 86 } 87 88 // 进行config初始化 89 cobra.OnInitialize(func() { 90 if useDefaultFlags { 91 // 初始化配置文件 92 if cli.configFile != "" { 93 cli.configFile, err = filepath.Abs(cli.configFile) 94 if err != nil { 95 return 96 } 97 cli.viper.SetConfigFile(cli.configFile) 98 } else { 99 // 如果含有环境类型,那么使用config_{env} 100 if cli.configEnv != "" { 101 cli.viper.SetConfigName("config_" + cli.configEnv) 102 } else { 103 cli.viper.SetConfigName("config") 104 } 105 // 添加读取的配置文件路径 106 cli.viper.AddConfigPath(".") 107 cli.viper.AddConfigPath("./conf") 108 } 109 // viper加载配置 110 if err = cli.viper.ReadInConfig(); err != nil { 111 return 112 } 113 } 114 cli.viper.AutomaticEnv() 115 116 if readConfigFunc != nil { 117 cli.readConfigFunc = readConfigFunc 118 cli.readConfigFunc(cli.viper) 119 } 120 121 // 观察配置变更 122 cli.watchConfig() 123 }) 124 return nil 125 } 126 127 // 监听配置文件是否改变,用于热更新 128 func (cli *Cli) watchConfig() { 129 cli.viper.WatchConfig() 130 cli.viper.OnConfigChange(func(e fsnotify.Event) { 131 fmt.Printf("Config file changed: %s\n", e.Name) 132 if cli.readConfigFunc != nil { 133 cli.readConfigFunc(cli.viper) 134 } 135 }) 136 } 137 138 // RootCmd 获取cobra.Command 139 func (cli *Cli) RootCmd() *cobra.Command { 140 return cli.rootCmd 141 } 142 143 // Viper 获取viper 144 func (cli *Cli) Viper() *viper.Viper { 145 return cli.viper 146 } 147 148 // AddCommands 往cobra.Command添加多个命令 149 func (cli *Cli) AddCommands(cmds ...Command) { 150 if cmds == nil { 151 return 152 } 153 cli.subCmds = cmds 154 for _, cmd := range cmds { 155 cli.rootCmd.AddCommand(cmd) 156 } 157 } 158 159 // GetCommands 获取所有的命令command 160 func (cli *Cli) GetCommands() []Command { 161 return cli.subCmds 162 } 163 164 // Execute 执行命令 165 func (cli *Cli) Execute() error { 166 return cli.rootCmd.Execute() 167 } 168 169 // Get 从配置文件中获取参数 170 func (cli *Cli) Get(key string) interface{} { 171 return cli.viper.Get(key) 172 } 173 174 // GetString 获取字符串参数 175 func (cli *Cli) GetString(key string) string { 176 return cli.viper.GetString(key) 177 } 178 179 // GetInt 获取int参数 180 func (cli *Cli) GetInt(key string) int { 181 return cli.viper.GetInt(key) 182 } 183 184 // GetInt64 获取int64参数 185 func (cli *Cli) GetInt64(key string) int64 { 186 return cli.viper.GetInt64(key) 187 } 188 189 // GetBool 获取bool参数 190 func (cli *Cli) GetBool(key string) bool { 191 return cli.viper.GetBool(key) 192 } 193 194 // GetConfigFile 获取配置文件 195 func (cli *Cli) GetConfigFile() string { 196 return cli.configFile 197 } 198 199 // GetConfigEnv 获取环境 200 func (cli *Cli) GetConfigEnv() string { 201 return cli.configEnv 202 } 203 204 // AppInfo 获取appInfo 205 func (cli *Cli) AppInfo() *AppInfo { 206 return cli.appInfo 207 }