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

How to iterate over yml sections with structs?

我用毒蛇。我正在尝试使用 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

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

如果我得到了你想要实现的目标,并且基于你提供的 for 循环;

  • 你真正需要的是一个 YAML sequence,它是一个 array。所以你最终的 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 密钥提供一个标签(和相应的结构字段),所以循环它不可能开箱即用,因为 emailskype 被解析为结构字段。原始 YAML 文件的结构示例为;

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

type User struct {
    Name     string   `mapstructure:"name"`
    Contacts Contacts `mapstructure:"contacts"`
}

type Contacts struct {
    Email Contact `mapstructure:"email"`
    Skype Contact `mapstructure:"skype"`
}

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

我认为唯一重要的问题是,在您的数据结构中,您已将 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