0

我有一个如下所示的配置格式:

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 无法做到,也愿意为支持此功能的库提供建议。

4

1 回答 1

0

首先,您应该定义标志。我不知道,根据您的示例,您是否这样做,但您应该做类似的事情(基于此):

    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
        }
    })

这对我有用。

于 2020-05-21T07:43:32.193 回答