dtdr84101 2019-05-08 21:59
浏览 1157

在Go中解组Yaml时,如何在列表中的键上设置默认值?

I have a YAML like one below.

connections:
  - name: demo
    hosts:
      - demo.example.com:9200
    username: admin
    password: password
    ssl: true
    ssl_verify: true
    version: 7
  - name: test
    hosts:
      - "test.example.com:9200"
    username: admin
    password: password

As you can see ssl and ssl_verify is not set in the second item of the list. I want them by default to be true, however, it is not happening. I tried different solutions.

  1. Viper defaults - does not work.
viper.SetDefault("connections[].ssl", "true")
  1. https://github.com/creasty/defaults - does not work.
type Config struct {
    Connections []struct {
        Name      string
        Hosts     []string
        Username  string
        Password  string
        Ssl       bool `default:"true"`
        SslVerify bool `default:"true"`
        Version   int
    }
}

...

err := defaults.Set(config)

  1. Manually looping through the list of structures. While these method work with strings, it does not work with boolean values because they are already initialized with false after unmarshalling and we don't know for sure whether false is entered by the user or not.

  2. Using pointers with boolean values. This works as uninitialized values are equal to nil and they are easy to catch. However, it will require to dereference pointers when using config struct, which is not very convenient. Alternatively, a new struct can be generated based on the one that comes from unmarshalling.

type Config struct {
    Connections []struct {
        Name      string
        Hosts     []string
        Username  string
        Password  string
        Ssl       *bool
        SslVerify *bool
        Version   int
    }
}
  1. Using hashmap instead of struct. This works because empty values are not initialized, however, it will require to run checks on the map elements before accessing them or to convert a map to the struct.

Solutions 4 and 5 will likely work, but I am wondering if there anything better than that.

Any ideas?

  • 写回答

2条回答 默认 最新

  • dongtan9253 2019-05-09 07:55
    关注

    You can use a function to do the job:

    type Connection struct {
        Name      string
        Hosts     []string
        Username  string
        Password  string
        Ssl       *bool
        SslVerify bool
        Version   int
    }
    
    // If Ssl is nil, returns true
    // otherwise the value
    func (c Connection) IsSSL() bool {
        return c.Ssl == nil || *c.Ssl
    }
    
    type Config struct {
        Connections []Connection
    }
    

    EDIT

    Or, even better, simply invert the logic of your booleans:

    type Connection struct {
        Name          string
        Hosts         []string
        Username      string
        Password      string
        SkipSsl       bool
        SkipSslVerify bool
        Version       int
    }
    

    This way, SSL would be used unless explicitly told different in the config - which would stand out when somebody reads the config.

    评论

报告相同问题?

悬赏问题

  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码