多種方式讀取 MySQL 資料庫配置

pardon110發表於2019-11-02

整合第三方庫,自檢測讀取配置檔案。檔案讀取,結構體定義,介面實現,錯誤返回,庫解析,適合新同學練手。

思路

  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.

擴充套件

可擴充套件解析方法,加日誌,加自定義解析,加命令列形式讀取....

相關文章