多种方式读取 MySQL 数据库配置

集成第三方库,自检测读取配置文件。文件读取,结构体定义,接口实现,错误返回,库解析,适合新同学练手。

思路

  1. 文件读取获取字节流
  2. 文件类型分析,确定解析api
  3. 集成第三方解析api管理器
  4. 定义目标配置的结构体及约束性接口
  5. 实现解析器接口方法及其构造方法

结构

目录

$GOPATH\src
├─demo 
│  ├─conf.json
│  ├─conf.yaml
│  ├─conf.xml
│  ├─main.go

conf.yaml

mysql:
    default: {
        host: 127.0.0.1:3306,
        dbname: test,
        username: root,
        password: default
    }
    ...

上码

package main

import (
    "encoding/json"
    "encoding/xml"
    "errors"
    "fmt"
    "io/ioutil"
    "path"
    "path/filepath"

    "gopkg.in/yaml.v2"
)

// DB 数据库配置
type DB struct {
    Host     string
    Dbname   string
    Username string
    Password string
}

// Config 配置
type Config struct {
    Mysql map[string]DB
}

// Action 行为约束 导入/解析
type Action interface {
    Type() string
    Load(filename string) error
    Resolve() (out interface{}, err error)
}

// Resolver 解析器
type Resolver struct {
    filename string
    conf     *Config
    in       []byte
}

// Manager 管理器 集成三方解析api
var Manager = map[string]func([]byte, interface{}) error{
    "yaml": yaml.Unmarshal,
    "json": json.Unmarshal,
    "xml":  xml.Unmarshal,
}

// New 初始化实例
func New() *Resolver {
    return &Resolver{conf: new(Config)}
}
// Name 文件名
func (r *Resolver) name() string {
    return filepath.Base(r.filename)
}
// Type 类型
func (r *Resolver) Type() string {
    return path.Ext(r.filename)[1:]
}

// Load 加载
func (r *Resolver) Load(filename string) (err error) {
    raw, err := ioutil.ReadFile(filename)
    if err != nil {
        return fmt.Errorf("加载错误: %v ", err)
    }
    r.filename = filename
    r.in = raw
    return nil
}

// Resolve 解析
func (r *Resolver) Resolve() (out interface{}, err error) {
    ext := r.Type()
    if unmarshal, ok := Manager[ext]; ok {
        err = unmarshal(r.in, r.conf)
    }
    if err != nil {
        return nil, errors.New("解析错误")
    }
    out = *r.conf
    return
}

func main() {
    filename := "conf.json"
    r := New()    // 1. 加载
    if err := r.Load(filename); err != nil {
        fmt.Printf("%v\n", err)
        return
    }

    data, err := r.Resolve()  // 解析
    if err != nil {
        fmt.Printf("%v\n", err)
        return
    }
    fmt.Printf("%s 解析%s:\n", r.Type(), r.name())
    fmt.Println(data)
}

效果

$ go run main.go
json 解析conf.json:
{map[data_center:{127.0.0.1:3306 test root data_center} default:{127.0.0.1:3306 test root default} slave_db01:{127.0.0.1:3306 test root slave_db01} user_center:{127.0.0.1:3306 test root user_center}]}

$ go run main.go
加载错误: open ssconf.yaml: The system cannot find the file specified.

扩展

可扩展解析方法,加日志,加自定义解析,加命令行形式读取....

本作品采用《CC 协议》,转载必须注明作者和本文链接
pardon110
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
开发者 @ 社科大
文章
134
粉丝
24
喜欢
101
收藏
55
排名:106
访问:8.9 万
私信
所有博文
社区赞助商