ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
## 可扩展部分 - 配置解析器 (原生集成 json 解析器) - 驱动构造器 (原生集成 mysql 构造器) ## 实现目标 - 新增 `toml` 配置解析器 ## 配置解析器结构分析 我们查看官方源码配置解析器目录`~/gorose/parser/`, 找到已有的`json`解析器, 实现方式是: 1. 定义统一解析器接口 (`interface.go`) ```go type IParser interface { Parse(d string) (conf *across.DbConfigCluster, err error) } ``` 2. 实现该接口解析 json (`json_parser.go`) ```go package parser import ( "encoding/json" "fmt" "io/ioutil" "reflect" "strings" ) type JsonConfigParser struct { } func init() { // 检查解析器是否实现了接口 var parserTmp IParser = &JsonConfigParser{} // 注册驱动 Register("json", parserTmp) } func (c *JsonConfigParser) Parse(file string, dbConfCluster interface{}) (err error) { var fp []byte fp, err = ioutil.ReadFile(file) if err != nil { return err } // 是否是主从格式 strFp := string(fp) if strings.Contains(strFp, "Slave") && strings.Contains(strFp, "Master") { err = json.Unmarshal(fp, dbConfCluster) } else { //err = json.Unmarshal([]byte(fp), &conf.Master) err = jsonDecoder(fp, dbConfCluster) } return err } func jsonDecoder(str []byte, dbConfCluster interface{}) (err error) { srcElem := reflect.Indirect(reflect.ValueOf(dbConfCluster)) fmt.Println(srcElem) fieldType := srcElem.FieldByName("Master").Type().Elem() fieldElem := reflect.New(fieldType) err = json.Unmarshal(str, fieldElem.Interface()) srcElem.FieldByName("Master").Set(fieldElem) return } ``` `json_parser.go`分析: - a. 定义 `type JsonConfigParser struct` - b. 实现解析器接口 `func (c *JsonConfigParser) Parse(file string, dbConfCluster interface{}) (err error)` - c. 在入口处`init()`方法中检查并注册解析器, 并定取名为 `json` 实现接口(b)的源码分析: - i. 获取 `across.DbConfigCluster` 数据库映射结构体对象 - ii: 读取文件 - iii: 解析配置 通过如上的源码分析, 我们不难发现, 只需要实现解析器接口, 并能够解析到配置结构体中即可, 下面, 我们就是先一个toml解析器来练练手 ## toml 解析器的实现 - 新增文件`~/gorose/parser/toml_parser.go` - 定义结构体 `type TomlConfigParser struct` - 实现方法 `func (c *TomlConfigParser) Parse(file string, dbConfCluster interface{}) (err error)` - 注册解析器 ```go func init() { // 检查解析器是否实现了接口 var parserTmp IParser = &TomlConfigParser{} // 注册解析器 Register("toml", parserTmp) } ``` - 完整源码 ```go package parser import ( "github.com/BurntSushi/toml" "io/ioutil" "reflect" "strings" ) type TomlConfigParser struct { } func init() { // 检查解析器是否实现了接口 var parserTmp IParser = &TomlConfigParser{} // 注册驱动 Register("toml", parserTmp) } func (c *TomlConfigParser) Parse(file string, dbConfCluster interface{}) (err error) { var fp []byte fp, err = ioutil.ReadFile(file) if err != nil { return } // 是否是主从格式 strFp := string(fp) if strings.Contains(strFp, "Slave") && strings.Contains(strFp, "Master") { err = toml.Unmarshal(fp, dbConfCluster) } else { //err = json.Unmarshal([]byte(fp), &conf.Master) err = tomlDecoder(fp, dbConfCluster) } return err } func tomlDecoder(str []byte, dbConfCluster interface{}) (err error) { srcElem := reflect.Indirect(reflect.ValueOf(dbConfCluster)) fieldType := srcElem.FieldByName("Master").Type().Elem() fieldPtr := reflect.New(fieldType) //tmp := fieldPtr.Interface() err = toml.Unmarshal(str, fieldPtr.Interface()) srcElem.FieldByName("Master").Set(fieldPtr) return } ``` 这里引入了第三方包 `github.com/BurntSushi/toml` 作为toml解析器, 并赋值给 `across.DbConfigCluster` 即可 同理, 我们可以实现任何文件类型的解析器 , 只需要能够最终返回 `across.DbConfigCluster` 的实现即可