package configure import ( "fmt" "io/ioutil" "os" "path" "reflect" "sync" jsoniter "github.com/json-iterator/go" ) var typeOfIn = reflect.TypeOf(([]map[string]interface{})(nil)).Elem() var typeOfError = reflect.TypeOf((*error)(nil)).Elem() type configurehandle struct { configureType reflect.Type fn reflect.Value } func newSys(options Options) (sys *Configure, err error) { sys = &Configure{ options: options, configurehandles: map[string]*configurehandle{}, configure: map[string]interface{}{}, } err = sys.init() return } type Configure struct { options Options hlock sync.RWMutex configurehandles map[string]*configurehandle clock sync.RWMutex configure map[string]interface{} } func (this *Configure) init() (err error) { return } //加载配置文件 func (this *Configure) RegisterConfigure(name string, fn interface{}) (err error) { this.hlock.RLock() _, ok := this.configurehandles[name] this.hlock.RUnlock() if ok { err = fmt.Errorf("重复 注册配置【%s】", name) return } fnvalue := reflect.ValueOf(fn) if fnvalue.Type().NumIn() != 1 { err = fmt.Errorf("LoadConfigure fn 类型错误! 只接受fn( _buf []map[string]interface{})(v,error) 函数参数") return } inType := fnvalue.Type().In(0) if inType.Elem() != typeOfIn { err = fmt.Errorf("LoadConfigure fn 类型错误! 只接受fn( _buf []map[string]interface{})(v,error) 函数参数") return } if fnvalue.Type().NumOut() != 2 { err = fmt.Errorf("LoadConfigure fn 类型错误! 只接受fn( _buf []map[string]interface{})(v,error) 函数参数") return } dataType := fnvalue.Type().Out(0) if dataType.Kind() != reflect.Ptr { err = fmt.Errorf("LoadConfigure fn 类型错误! 只接受fn( _buf []map[string]interface{})(v,error) 函数参数") return } if returnType := fnvalue.Type().Out(1); returnType != typeOfError { err = fmt.Errorf("LoadConfigure fn 类型错误! 只接受fn( _buf []map[string]interface{})(v,error) 函数参数") return } handle := &configurehandle{ configureType: dataType, fn: fnvalue, } if err = this.loaderConfigure(name, handle); err != nil { return } this.hlock.Lock() this.configurehandles[name] = handle this.hlock.Unlock() return } //更新配置信息 func (this *Configure) UpdateConfigure(names ...string) (err error) { for _, v := range names { this.hlock.RLock() handle, ok := this.configurehandles[v] this.hlock.RUnlock() if !ok { err = fmt.Errorf("no RegisterConfigure:%s", v) return } if err = this.loaderConfigure(v, handle); err != nil { err = fmt.Errorf("loaderConfigure:%s err:%v", v, err) return } } return } //读取配置文件 func (this *Configure) GetConfigure(name string) (v interface{}, err error) { this.clock.RLock() v, ok := this.configure[name] this.clock.RUnlock() if !ok { err = fmt.Errorf("no LoadConfigure:%s", name) } return } //加载配置文件 func (this *Configure) loaderConfigure(name string, handle *configurehandle) (err error) { var ( fliepath string file *os.File bytes []byte data []map[string]interface{} returnValues []reflect.Value ) fliepath = path.Join(this.options.ConfigurePath, name) if file, err = os.Open(fliepath); err != nil { err = fmt.Errorf("no fond file:%s", fliepath) return } defer file.Close() if bytes, err = ioutil.ReadAll(file); err != nil { err = fmt.Errorf("read file:%s err:%v", fliepath, err) return } if err = jsoniter.Unmarshal(bytes, &data); err != nil { err = fmt.Errorf("read file:%s json.Unmarshal err:%v", fliepath, err) return } returnValues = handle.fn.Call([]reflect.Value{reflect.ValueOf(data)}) errInter := returnValues[1].Interface() if errInter != nil { err = fmt.Errorf("read file:%s load.fn err:%v", fliepath, errInter) return } this.clock.Lock() this.configure[name] = returnValues[0].Interface() this.clock.Lock() return }