# #go #go-cobra
Вопрос:
У меня есть следующая модель конфигурации:
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 = amp;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(amp;name, "name", "n", "", "Your name")
rootCmd.Flags().StringVarP(amp;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(amp;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: %sn", config.Name)
fmt.Printf("Project name: %sn", 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
«Я получу трассировку стека». Вопрос в том, как добавить этот (и другие атрибуты) в качестве первого элемента в массиве сложных объектов? Могу ли я получить вторую гадюку, которая будет считываться в другой объект, а затем добавляться в основную конфигурацию, или есть другой способ?
Ответ №1:
После игры с этим у меня есть ответ.
Несмотря на то , что я настроил конфигурацию так, чтобы в ней был фрагмент проекта Project []Project
, Viper достаточно умен, чтобы разобраться в этом.
Поэтому, чтобы привязать имя проекта к первому элементу среза, достаточно просто использовать:
viper.BindPFlag("project.name", runCmd.Flags().Lookup("name"))
Индекс не требуется. Однако я могу распечатать значение с помощью:
fmt.Println(Config.Project[0].Name)
Я перестарался, думая об этом