我有一些用于处理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 }