1

我使用cobraviper编写了一个简单的 CLI 工具。我最近一直在重构它以避免包全局变量,主要是因为使用 eg 建议的布局很难测试cobra init

代替...

var rootCmd = &cobra.Command{
  ...
}

func main() {
  rootCmd.Execute()
}

我有更多类似的东西:

func NewCmdRoot() *cobra.Command {
  cmd := &cobra.Command{
    ...
  }

  return cmd
}

func main() {
  rootCmd := NewCmdRoot()
  rootCmd.Execute()
}

这实际上效果很好,并且使测试从一组干净的 cli 选项开始变得更加容易。我在将 Viper 集成到新方案中时遇到了一些困难。如果我只关心 root 命令,我可以在PersistentPreRun 命令中进行设置,如下所示:

func initConfig(cmd *cobra.Command) {
  config := viper.New()
  rootCmd := cmd.Root()

  config.BindPFlag("my-nifty-option", rootCmd.Flag("my-nifty-option")); err != nil {

  // ...stuff happens here...

  config.ReadInConfig()

  // What happens next?
}

func NewCmdRoot() *cobra.Command {
  cmd := &cobra.Command{
    PersistentPreRun: func(cmd *cobra.Command, args []string) {
      initConfig(cmd)
    },
  }

这种工作方式:只要我只对与 Cobra 命令行选项相对应的配置选项感兴趣,事情就会按预期工作。但是如果我想访问config变量本身呢?

我不确定如何config在方法之外公开变量 initConfig而不将其转换为全局包。我想要实例化多个命令树的可能性,每个命令树都有自己独立的 Viper 配置对象,但我不清楚把它放在哪里。

4

0 回答 0