如何使用结构迭代 yml 部分?

时间:2021-07-16 09:53:31

标签: go viper-go

我使用毒蛇。我正在尝试使用 yml-config 从结构中获取信息。

type Config struct {
    Account       User           `mapstructure:"user"`      
}

type User struct {
    Name       string           `mapstructure:"name"`
    Contacts   []Contact        `mapstructure:"contact"`
}

type Contact struct {
    Type          string          `mapstructure:"type"`
    Value         string          `mapstructure:"value"`
}

func Init() *Config {
    conf := new(Config)

    viper.SetConfigType("yaml")
    viper.ReadInConfig()
    ...
    viper.Unmarshal(conf)
    return conf
}

...
config := Init()
...
for _, contact := range config.Account.Contacts {
   type := contact.type
   vlaue := contact.value
}

和 config.yml

user:
  name: John
  contacts:
    email:
      type: email
      value: test@test.com
    skype:
      type: skype
      value: skypeacc

我可以得到这样的结构物品吗?我无法获得这样的联系数据。可能吗?

2 个答案:

答案 0 :(得分:0)

如果我根据您提供的 for 循环正确理解了您想要实现的目标;

  • 您真正需要的是一个 YAML 序列,它是一个数组。所以你最终的 YAML 文件应该是这样的;
user:
  name: John
  contacts:
      - type: email
        value: test@test.com
      - type: skype
        value: skypeacc
      - type: email
        value: joe@example.com
  • 此外,您在 Contacts 切片上的标签中存在拼写错误。它应该匹配 YAML 密钥;
type User struct {
   Name     string    `mapstructure:"name"`
   Contacts []Contact `mapstructure:"contacts"`
}

如果您希望保留原始的 YAML 文件结构,您必须为每个 YAML 键提供一个标签(和相应的结构字段),因此不可能开箱即用地循环遍历它,因为 {{1} } 和 email 被解析为结构体字段。原始 YAML 文件的结构示例是;

skype

答案 1 :(得分:0)

我认为唯一重要的问题是,在您的数据结构中,您已将 Contacts 声明为列表,但在您的 YAML 文件中,它是一个字典。如果你这样构造你的输入文件:

user:
  name: John
  contacts:
    - type: email
      value: test@test.com
    - type: skype
      value: skypeacc

然后你可以这样读:

package main

import (
    "fmt"

    "github.com/spf13/viper"
)

type Config struct {
    User User
}

type User struct {
    Name     string
    Contacts []Contact
}

type Contact struct {
    Type  string
    Value string
}

func main() {
    var cfg Config

    viper.SetConfigName("config")
    viper.AddConfigPath(".")
    err := viper.ReadInConfig()
    if err != nil {
        panic(err)
    }
    viper.Unmarshal(&cfg)
    fmt.Println("user: ", cfg.User.Name)
    for _, contact := range cfg.User.Contacts {
        fmt.Println("  ", contact.Type, ": ", contact.Value)
    }
}

上面的代码可以按原样运行;你应该可以放下它 成一个文件并构建它。当我运行上面的例子时,我得到 输出:

user:  John
   email :  test@test.com
   skype :  skypeacc