【问题标题】:What's the idiomatic way of parsing dynamic YAML in Go?在 Go 中解析动态 YAML 的惯用方式是什么?
【发布时间】:2018-02-04 01:17:39
【问题描述】:

我有一些用于处理 YAML 配置文件的代码,该文件在使用类型断言时有点失控,我觉得必须有更好的方法来做到这一点。

这是我的配置文件中的相关 sn-p:

plugins:
  taxii20:
    default: default
    api_roots:
      default:
        auth:
          - ldap
          - mutualtls
        collections:
          all:
            selector: g.V().Save("<type>").Save("<created>").All()
            selector_query_lang: gizmo

这是我的解析代码:

func parseTaxiiConfig() {
    plg.ConfigMutex.Lock()
    taxiiConfig := plg.ConfigData.Plugins["taxii20"].(map[interface{}]interface{})
    ConfigData = &Config{}
    if taxiiConfig["default"] != nil {
        ConfigData.DefaultRoot = taxiiConfig["default"].(string)
    }
    if taxiiConfig["api_roots"] != nil {
        ConfigData.APIRoots = make([]model.APIRoot, 0)
        iroots := taxiiConfig["api_roots"].(map[interface{}]interface{})
        for iname, iroot := range iroots {
            root := model.APIRoot{Name: iname.(string)}
            authMethods := iroot.(map[interface{}]interface{})["auth"].([]interface{})
            root.AuthMethods = make([]string, 0)
            for _, method := range authMethods {
                root.AuthMethods = append(root.AuthMethods, method.(string))
            }
            collections := iroot.(map[interface{}]interface{})["collections"].(map[interface{}]interface{})
            root.Collections = make([]model.Collection, 0)
            for icolName, icollection := range collections {
                collection := model.Collection{Name: icolName.(string)}
                collection.Selector = icollection.(map[interface{}]interface{})["selector"].(string)
                collection.SelectorQueryLang = icollection.(map[interface{}]interface{})["selector_query_lang"].(string)
                root.Collections = append(root.Collections, collection)
            }
            ConfigData.APIRoots = append(ConfigData.APIRoots, root)
        }
    }
    plg.ConfigMutex.Unlock()

    // debug
    fmt.Println(ConfigData)
}

代码按预期工作,但这里有太多类型断言,我无法摆脱我错过了更好方法的感觉。

正如配置所暗示的,一个可能的关键事项是,这是针对 Caddy 样式插件系统的配置,因此主配置解析器无法提前知道插件配置的形状。它必须将配置文件的插件部分的处理委托给插件本身。

【问题讨论】:

  • 实际上,我找到了我同事的一些代码,用github.com/mitchellh/mapstructure 解决了这个问题——如果我能解决这个问题,我会尽快更新这个问题。

标签: go yaml


【解决方案1】:

这就是我想出的。更具可读性。

// Config represents TAXII 2.0 plugin structure
type Config struct {
    DefaultRoot string
    APIRoots    []model.APIRoot
}

// Intermediate config for mapstructure
type configRaw struct {
    DefaultRoot string                `mapstructure:"default"`
    APIRoots    map[string]apiRootRaw `mapstructure:"api_roots"`
}
type apiRootRaw struct {
    AuthMethods []string                 `mapstructure:"auth"`
    Collections map[string]collectionRaw `mapstructure:"collections"`
}
type collectionRaw struct {
    Selector          string `mapstructure:"selector"`
    SelectorQueryLang string `mapstructure:"selector_query_lang"`
}

func parseTaxiiConfig() error {
    plg.ConfigMutex.Lock()
    defer plg.ConfigMutex.Unlock()

    taxiiConfig := plg.ConfigData.Plugins["taxii20"].(map[interface{}]interface{})
    fmt.Println(taxiiConfig)
    ConfigData = &Config{}
    raw := &configRaw{}
    err := mapstructure.Decode(taxiiConfig, raw)
    if err != nil {
        return err
    }

    ConfigData.DefaultRoot = raw.DefaultRoot
    ConfigData.APIRoots = make([]model.APIRoot, 0)
    for name, root := range raw.APIRoots {
        apiRoot := model.APIRoot{Name: name}
        apiRoot.AuthMethods = root.AuthMethods
        apiRoot.Collections = make([]model.Collection, 0)
        for colName, col := range root.Collections {
            collection := model.Collection{Name: colName}
            collection.Selector = col.Selector
            collection.SelectorQueryLang = col.SelectorQueryLang
            apiRoot.Collections = append(apiRoot.Collections, collection)
        }
        ConfigData.APIRoots = append(ConfigData.APIRoots, apiRoot)
    }

    return nil
}

【讨论】:

    猜你喜欢
    • 2013-01-03
    • 1970-01-01
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 2014-06-23
    • 1970-01-01
    • 2019-03-03
    相关资源
    最近更新 更多