Каким образом флаг Кобры типа `StringToStringVar` доступен с помощью Viper? - PullRequest
0 голосов
/ 18 октября 2019

Я пытаюсь разработать приложение на Go, которое принимает входные данные из командной строки в виде строки пар ключ-значение. Для этого я использую StrngToStringVar из библиотеки Cobra.

Я также использую Viper для привязки этих флагов к конфигурации, однако, какое бы значение я ни ставил, мне кажется, что я не могу получить его от Viper. .

Это код

package main

import (
    "fmt"

    "github.com/spf13/cobra"
    "github.com/spf13/viper"

    "github.com/davecgh/go-spew/spew"
)

func main() {
    var items map[string]string
    var name string

    rootCmd := &cobra.Command{
        Use:   "cobra",
        Short: "Test options on the command line",
        Long:  ``,
        Run: func(ccmd *cobra.Command, args []string) {

            spew.Dump(viper.GetString("name"))
            spew.Println("")

            fmt.Println("GetStringMap")
            spew.Dump(viper.GetStringMap("items"))

            fmt.Println("")

            fmt.Println("GetStringMapString")
            spew.Dump(viper.GetStringMapString("items"))
        },
    }

    rootCmd.Flags().StringVar(&name, "name", "", "Name of the list")
    rootCmd.Flags().StringToStringVar(&items, "item", nil, "Map stating the items to be included")

    viper.BindPFlag("name", rootCmd.Flags().Lookup("name"))
    viper.BindPFlag("items", rootCmd.Flags().Lookup("item"))

    rootCmd.Execute()
}

Если я запускаю это с командой go run .\main.go --item shopping=apple,banana --name foobar, я получаю следующий результат

(string) (len=6) "foobar"

GetStringMap
(map[string]interface {}) {
}

GetStringMapString
(map[string]string) {
}

Как можно увидеть выводне содержит ничего для элементов, хотя я правильно установил ввод (я считаю). Я пытался использовать PR https://github.com/spf13/pflag/pull/133, чтобы понять, как это сделать, но мне не повезло.

Мне интересно, если привязка неверна, но я успешно использовал CObra вдругие проекты, поэтому я не понимаю, как ссылаться на сгенерированный map[string]string из Cobra.

1 Ответ

0 голосов
/ 20 октября 2019

Что касается обязательной части, это правильно. Однако перед обработкой вы можете проверить, существует ли определенный ключ, с помощью vipver.IsSet () , распечатать все доступные ключи с помощью viper.AllKeys () или распечатать все с помощью viper.AllSettings () .

Вот пример (test.go):

package main

import (
    "fmt"

    "github.com/spf13/cobra"
    "github.com/spf13/viper"
)

func main() {
    var items map[string]string

    rootCmd := &cobra.Command{
        Use: "app",
        Run: func(ccmd *cobra.Command, args []string) {

            fmt.Println("item exists?", viper.IsSet("item"))
            fmt.Println("GetString  :", viper.GetString("item"))
            fmt.Println("Keys       :", viper.AllKeys())
            fmt.Println("Settings   :", viper.AllSettings())
        },
    }

    rootCmd.Flags().StringToStringVarP(&items, "item", "i", nil, "Map stating the items to be included")
    viper.BindPFlag("item", rootCmd.Flags().Lookup("item"))
    rootCmd.Execute()
}

Вывод:

$ ./test.exe -i 'k=v,"a=b,c"'
item exists? true
GetString  : [k=v,"a=b,c"]
Keys       : [item]
Settings   : map[item:[k=v,"a=b,c"]]

ИспользованиеGetStringMap() и GetStringMapString() имеет больше смысла с другими форматами, такими как JSON, YAML и т. Д. Вы можете отслеживать выполнение этих функций по вызовам демаршаллинга JSON в режиме отладки.

Для преобразования карты вы можете написать свойсобственная функция, подобная этой ( live ):

func getStringMap(s string) map[string]string {
    entries := strings.Split(s, ",")

    m := make(map[string]string)
    for _, e := range entries {
        tokens := strings.Split(e, "=")
        k := strings.TrimSpace(tokens[0])
        v := strings.TrimSpace(tokens[1])
        m[k] = v
    }

    return m
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...