1 Star 0 Fork 0

Saroth / goutil

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
config.go 3.57 KB
一键复制 编辑 原始数据 按行查看 历史
huanglf 提交于 2020-11-16 00:53 . 调整部分命名
package goutil
import (
"fmt"
"path"
"strings"
"time"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
)
// 子配置文件属性
type SubConfig struct {
name string // 子配置名
path string // 配置路径
active bool // 启用
}
// 配置信息结构体. 扩展Viper以支持多配置
type GoutilConfig struct {
*viper.Viper
// 以下成员重载时不会被重置
subConfigs map[string]SubConfig // 子配置
configFile string // 主配置文件路径
filePrefix string // 路径/文件名前缀_
fileExt string // 文件名后缀
isReload bool // 重载配置标志
onReload func(fsnotify.Event) // 重载处理.
}
func setAllAsDefault(dst, src *viper.Viper) {
for k, v := range src.AllSettings() {
dst.SetDefault(k, v)
}
}
func (s *GoutilConfig) loadConfig(path string, tmp *viper.Viper) bool {
if tmp == nil {
tmp = s.Viper
}
setAllAsDefault(tmp, tmp)
tmp.SetConfigFile(path)
res := ""
if err := tmp.ReadInConfig(); err != nil {
res = fmt.Sprintf("Config [%s] load failed: %s.\n", path, err)
}
if s.isReload {
if res != "" {
fmt.Printf(time.Now().Format("2006-01-02 15:04:05 ") + res)
return false
}
return true
}
if res != "" {
panic(fmt.Errorf(time.Now().Format("2006-01-02 15:04:05 ") + res))
}
s.WatchConfig()
s.OnConfigChange(s.reloadAll())
return true
}
// 加载主配置文件
func (s *GoutilConfig) SetConfig(file string) {
if s.isReload {
panic(fmt.Errorf("In reload state, should never happen!\n"))
}
if s.Viper == nil {
s.Viper = viper.New()
}
s.loadConfig(file, nil)
filePath, fileName := path.Split(file)
s.fileExt = path.Ext(fileName)
s.filePrefix = filePath + strings.TrimSuffix(fileName, s.fileExt) + "_"
s.configFile = file
s.subConfigs = make(map[string]SubConfig)
}
// 加载一个或多个子配置.
// subs: 子配置文件名. 前缀为主配置文件的`路径+文件名`, 后缀名同主配置文件
// tips:
// - 加载子配置前必须先加载主配置文件.
// - 多配置数据合并规则为向左覆盖.
// - 不支持动态设置子配置
func (s *GoutilConfig) SetSubConfigs(subs ...string) {
if s.configFile == "" {
panic(fmt.Errorf("No config loaded. " +
"It's required before load sub-configs.\n"))
}
if s.isReload {
panic(fmt.Errorf("In reload state, should never happen!\n"))
}
for _, f := range subs {
sub, ok := s.subConfigs[f]
if ok {
fmt.Printf("Duplicate sub-config: %s, skip!\n", f)
continue
}
sub = SubConfig{
name: f,
path: s.filePrefix + f + s.fileExt,
active: true,
}
s.subConfigs[f] = sub
s.loadConfig(sub.path, nil)
}
}
// 重载预设的所有配置文件
func (s *GoutilConfig) reloadAll() func(fsnotify.Event) {
return func(e fsnotify.Event) {
s.isReload = true
tmp := viper.New()
if ret := s.loadConfig(s.configFile, tmp); ret == false {
return
}
for _, f := range s.subConfigs {
if ret := s.loadConfig(f.path, tmp); ret == false {
return
}
}
setAllAsDefault(s.Viper, tmp)
s.isReload = false
if s.onReload != nil {
s.onReload(e)
}
}
}
// 配置初始化
// file: 主配置文件. 可以是相对路径
// subs: 子配置文件后缀
func NewConfig(file string, subs ...string) *GoutilConfig {
c := GoutilConfig{}
c.SetConfig(file)
c.SetSubConfigs(subs...)
return &c
}
// 设置主/子配置文件被修改后的处理, 只需设置一次
func (s *GoutilConfig) OnConfigReload(f func(fsnotify.Event)) {
s.onReload = f
}
// 获取所有配置数据
func (s *GoutilConfig) GetAll() map[string]interface{} {
return s.AllSettings()
}
Go
1
https://gitee.com/irontec/goutil.git
git@gitee.com:irontec/goutil.git
irontec
goutil
goutil
v0.1.0

搜索帮助