问题描述
我有以下配置模型:
type Config struct {
Project []Project `mapstructure:"project"`
}
type Project struct {
Name string `mapstructure:"name"`
}
我希望能够使用配置文件以及命令行上的选项进行配置。我知道如何通过以正确的格式传递配置文件然后对其进行解组来处理配置文件。
但是,我无法弄清楚如何使用 Cobra 在命令行上设置项目名称,然后让 Viper 将该值绑定为项目数组中的第一项。
package main
import (
"fmt"
"log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
type Config struct {
Project []Project `mapstructure:"project"`
Name string `mapstructure:"name"`
}
type Project struct {
Name string `mapstructure:"name"`
}
var (
config Config
rootCmd = &cobra.Command{
Use: "rjsdummy",Short: "Dummy app to understand Viper BindPFlags",Long: "",PersistentPreRun: preRun,Run: executeRun,}
)
func init() {
var name string
var project_name string
cobra.OnInitialize()
// configure the flags on the command line
rootCmd.Flags().StringVarP(&name,"name","n","","Your name")
rootCmd.Flags().StringVarP(&project_name,"project","p","Project name")
// bind the flags to the configuration
viper.BindPFlag("name",rootCmd.Flags().Lookup(("name")))
viper.BindPFlag("project.0.name",rootCmd.Flags().Lookup(("project")))
}
func preRun(ccmd *cobra.Command,args []string) {
err := viper.Unmarshal(&config)
if err != nil {
log.Fatalf("Unable to read Viper options into configuration: %v",err)
}
}
func executeRun(ccmd *cobra.Command,args []string) {
fmt.Printf("Your name: %s\n",config.Name)
fmt.Printf("Project name: %s\n",config.Project[0].Name)
}
func main() {
rootCmd.Execute()
}
当我使用命令 go run .\binding.go -n Russell -p Turtle
运行它时,我得到以下输出:
所以我知道 viper.BindPFlag("project.0.name",rootCmd.Flags().Lookup(("project")))
行不起作用。如果我将其更改为 project[0].name
,我会得到一个堆栈跟踪。问题是如何将这个(和其他属性)添加为复杂对象数组中的第一项?我可以有第二个 Viper 来读入另一个对象然后添加到主配置中还是有其他方法?