在 Go 中解析动态 YAML 的惯用方法是什么?



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

这是我的配置文件中的相关代码片段:

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 风格的插件系统的配置,因此主配置解析器无法提前知道插件配置的形状会是什么样子。它必须将配置文件中插件部分的处理委托给插件本身。

这是我想到的。更具可读性。

// 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
}

相关内容

最新更新