Config

实现config主要目标为了集成配置库,然后实现框架一体化,完美将配置融合到框架中,Config作为eudore.App的一部分然后全局传递。

Config主要方法未Get/Set来读写数据,和ParseFuncs和Parse来解析数据。

// ConfigParseFunc 定义配置解析函数。
//
// Config 默认解析函数为eudore.ConfigAllParseFunc
type ConfigParseFunc func(Config) error

/*
Config 定义配置管理,使用配置读写和解析功能。

Get/Set读写数据实现下列功能:
    使用自定义map或struct作为数据存储
    支持Lock并发安全
    基于字符串路径层次访问属性

默认解析函数实现下列功能:
    自定义配置解析函数
    解析多json文件
    解析命令行参数
    解析Env环境变量
    配置差异化
    切换工作目录
*/
type Config interface {
    Get(string) interface{}
    Set(string, interface{}) error
    ParseOption([]ConfigParseFunc) []ConfigParseFunc
    Parse() error
}

ConfigMap

// configMap 使用map保存配置。
type configMap struct {
    Keys   map[string]interface{} `alias:"keys"`
    Print  func(...interface{})   `alias:"print"`
    funcs  []ConfigParseFunc      `alias:"-"`
    Locker sync.RWMutex           `alias:"-"`
}

example

configmap使用map[string]interface{}作为配置存储,包含Locker作为读写锁保证并发安全,可以视为一个map存储的配置。

Get/Set方法只进行读写锁操作map。

// Get 方法获取一个属性,如果键为空字符串,返回保存全部数据的map对象。
func (c *configMap) Get(key string) interface{} {
    c.Locker.RLock()
    defer c.Locker.RUnlock()
    if len(key) == 0 {
        return c.Keys
    }
    return c.Keys[key]
}

// Set 方法设置一个属性,如果键为空字符串且值类型是map[string]interface{},则替换保存全部数据的map对象。
func (c *configMap) Set(key string, val interface{}) error {
    c.Locker.Lock()
    if len(key) == 0 {
        keys, ok := val.(map[string]interface{})
        if ok {
            c.Keys = keys
        }
    } else if key == "print" {
        fn, ok := val.(func(...interface{}))
        if ok {
            c.Print = fn
        } else {
            c.Print(val)
        }
    } else {
        c.Keys[key] = val
    }
    c.Locker.Unlock()
    return nil
}

ConfigEuodre

// configEudore 使用结构体或map保存配置,通过属性或反射来读写属性。
type configEudore struct {
    Keys          interface{}          `alias:"keys"`
    Print         func(...interface{}) `alias:"print"`
    funcs         []ConfigParseFunc    `alias:"-"`
    configRLocker `alias:"-"`
}

type configRLocker interface {
    sync.Locker
    RLock()
    RUnlock()
}

example

configeudore使用自定义结构体来存储配置,如果Get/Set的key路径中含有'.'就会使用eudore.Get/eudore.Set方法来按路径一层层的选择对象属性。

NewConfigEudore函数就直接创建一个configEudore,如果配置存储对象实现读写锁接口,就会使用配置存储对象的读写锁方法,直接可以使用外部传递的读写锁方法。

Get/Set方法时使用的Get/Set函数去访问结构体和map的属性,也可以直接使用配置存储结构体访问属性。

// NewConfigEudore 创建一个ConfigEudore,如果传入参数为空,使用空map[string]interface{}作为初始化数据。
//
// ConfigEduoew允许传入一个map或struct作为配置存储,使用eudore.Set和eudore.Get方法去读写数据。
//
// 如果传入的配置对象实现sync.RLock一样的读写锁,则使用配置的读写锁,否则会创建一个sync.RWMutex锁。
//
// ConfigEduoe已实现json.Marshaler和json.Unmarshaler接口.
func NewConfigEudore(i interface{}) Config {
    if i == nil {
        i = make(map[string]interface{})
    }
    mu, ok := i.(configRLocker)
    if !ok {
        mu = new(sync.RWMutex)
    }
    return &configEudore{
        Keys:          i,
        Print:         printEmpty,
        funcs:         ConfigAllParseFunc,
        configRLocker: mu,
    }
}

// Get 方法实现读取数据属性的一个属性。
func (c *configEudore) Get(key string) (i interface{}) {
    if len(key) == 0 {
        return c.Keys
    }
    c.RLock()
    i = Get(c.Keys, key)
    c.RUnlock()
    return
}

// Set 方法实现设置数据的一个属性。
func (c *configEudore) Set(key string, val interface{}) (err error) {
    c.Lock()
    if len(key) == 0 {
        c.Keys = val
    } else if key == "print" {
        fn, ok := val.(func(...interface{}))
        if ok {
            c.Print = fn
        } else {
            c.Print(val)
        }
    } else {
        err = Set(c.Keys, key, val)
    }
    c.Unlock()
    return
}

ConfigParse

type ConfigParseFunc func(Config) error定义了配置解析函数,通过加载配置解析函数来解析配置,在Config接口中,ParseFuncs方法来修改Config的解析函数,最后调用Parse来解析全部配置。

例如ParseFuncs追加解析函数,ParseFuncs参数是当前的解析函数,返回新的解析函数,最后安顺序执行解析行为。

var c, _ := NewConfig("", nil)
// 追加一个解析函数
c.ParseFuncs(func(fn []ConfigParseFunc) []ConfigParseFunc{
    return append(fn, func(c Config) error {
        // 解析配置
        return nil
    })
})
c.Parse()

目前Config默认内置了六个解析函数,后续按顺序介绍。

ConfigParseRead

使用keys.config 读取到配置信息,然后多种方式读取到并存储给keys.configdata,然后后续解析。

func ConfigParseRead(c Config) error {
    path := GetString(c.Get("keys.config"))
    if path == "" {
        return nil //fmt.Errorf("config data is null")
    }
    // read protocol
    // get read func
    s := strings.SplitN(path, "://", 2)
    fn := ConfigLoadConfigReadFunc(s[0])
    if fn == nil {
        // use default read func
        fmt.Println("undefined read config: " + path + ", use default file:// .")
        fn = ConfigLoadConfigReadFunc("default")
    }
    data, err := fn(path)
    c.Set("keys.configdata", data)
    return err
}

ConfigParseConfig

解析读取到的配置信息。

// ConfigParseConfig 函数获得'keys.configdata'的内容解析配置。
func ConfigParseConfig(c Config) error {
    data := c.Get("keys.configdata")
    if data == nil {
        return nil
    }
    switch c.Get("keys.configtype") {
    case "json":
        return json.Unmarshal(data.([]byte), c)
    case "xml":
        return xml.Unmarshal(data.([]byte), c)
    }
    return nil
}

ConfigParseArgs

ConfigParseArgs函数解析命令行参数,必要是"--"开头,例如--keys.help=1,对应的执行函数就是c.Set("keys.help", "1"),来设置配置数据。

func ConfigParseArgs(c Config) (err error) {
    for _, str := range os.Args[1:] {
        if !strings.HasPrefix(str, "--") {
            continue
        }
        c.Set(split2byte(str[2:], '='))
    }
    return
}

ConfigParseEnvs

ConfigParseEnvs解析环境变量配置,配置必须要"ENV"开头,例如ENV_KEYS_HELP=1,前缀ENV删除,后续配置路径转换成小写,'-'替换成'.',对于命令行是--keys.help=1,对应的执行函数就是c.Set("keys.help", "1")

func ConfigParseEnvs(c Config) error {
    for _, value := range os.Environ() {
        if strings.HasPrefix(value, "ENV_") {
            k, v := split2byte(value, '=')
            k = strings.ToLower(strings.Replace(k, "_", ".", -1))[4:]
            c.Set(k, v)
        }
    }
    return nil
}

ConfigParseMods

ConfigParseMods用于差异化配置,先获取enable的字符串数组的数组,表示启用那些模式,处理[]interface{}用于兼容。

然后读取对于的mods.xxx的数据,使用ConvertTo函数来加载对应的配置数据。

func ConfigParseMods(c Config) error {
    mod, ok  := c.Get("enable").([]string)
    if !ok {
        modi, ok := c.Get("enable").([]interface{})
        if ok {
            mod = make([]string, len(modi))
            for i, s := range modi {
                mod[i] = fmt.Sprint(s)
            }
        }else {
            return nil
        }
    }

    for _, i := range mod {
        ConvertTo(c.Get("mods." + i), c.Get(""))
    }
    return nil
}

ConfigParseHelp

ConfigParseHelp的作用是输出当前配置信息,当前实现是检查keys.help key是否存在,存在则使用json输出到标准输出。

func ConfigParseHelp(c Config) error {
    ok := c.Get("keys.help") != nil
    if ok {
        JSON(c)
    }
    return nil
}

GetWarp

GetWarp提供封装func(string) interface{}类型函数实现,转换一个interface{}类型为指定类型,可以通过App或Config或func创建GetWarp对象,然后获取数据并转换类型。

type GetWarp
    func NewGetWarp(fn func(string) interface{}) GetWarp
    func NewGetWarpWithApp(app *App) GetWarp
    func NewGetWarpWithConfig(c Config) GetWarp
    func NewGetWarpWithObject(obj interface{}) GetWarp
    func (fn GetWarp) GetBool(key string, vals ...bool) bool
    func (fn GetWarp) GetBytes(key string) []byte
    func (fn GetWarp) GetFloat32(key string, vals ...float32) float32
    func (fn GetWarp) GetFloat64(key string, vals ...float64) float64
    func (fn GetWarp) GetInt(key string, vals ...int) int
    func (fn GetWarp) GetInt64(key string, vals ...int64) int64
    func (fn GetWarp) GetInterface(key string) interface{}
    func (fn GetWarp) GetString(key string, vals ...string) string
    func (fn GetWarp) GetStrings(key string) []string
    func (fn GetWarp) GetUint(key string, vals ...uint) uint
    func (fn GetWarp) GetUint64(key string, vals ...uint64) uint64

results matching ""

    No results matching ""