我有一个配置格式,如下所示:
type config struct {
FooBar string `mapstructure:"foo_bar"`
BazBot string `mapstructure:"baz_bot"`
}
我基于 Cobra 的 CLI 有带破折号的标志(例如--foo-bar=value1 --baz-bot=value2
(。
Viper 不知道如何在 CLI 中设置它们以覆盖配置文件值时将它们正确映射到配置中。这里有解决方案吗?Viper 配置设置如下所示:
func loadConfig(cmd *cobra.Command) (*config, error) {
res := &config{}
if err := viper.BindPFlags(cmd.Flags()); err != nil {
return nil, err
}
viper.SetEnvPrefix("K")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))
viper.AutomaticEnv()
var useConfigFile bool
if configFile, _ := cmd.Flags().GetString("config"); configFile != "" {
useConfigFile = true
viper.SetConfigFile(configFile)
}
if useConfigFile {
if err := viper.ReadInConfig(); err != nil {
return nil, err
}
if err := viper.Unmarshal(res); err != nil {
return nil, err
}
}
return res, nil
}
如果 viper 无法做到这一点,也愿意接受支持此功能的库的建议。
首先,你应该定义标志。我不知道,根据你的例子,你是否这样做,但你应该做类似的事情(基于这个(:
cfg := &config{}
val := reflect.ValueOf(cfg).Elem()
for i := 0; i < val.NumField(); i++ {
fieldType := val.Type().Field(i)
name := fieldType.Tag.Get("mapstructure")
rootCmd.PersistentFlags().String(strings.ReplaceAll(name, "_", "-"), "default", "usage")
}
有了这个,--help
命令将显示可用的标志(--foo-bar
和--baz-bot
(。
然后,您应该在loadConfig
方法中绑定标志:
cmd.Flags().VisitAll(func(flag *pflag.Flag) {
if err := viper.BindPFlag(strings.ReplaceAll(flag.Name, "-", "_"), flag); err != nil {
return
}
})
这对我有用。