github.com/volts-dev/volts@v0.0.0-20240120094013-5e9c65924106/config/config.go (about) 1 package config 2 3 import ( 4 "log" 5 "path/filepath" 6 "strings" 7 "sync" 8 "time" 9 10 "github.com/volts-dev/utils" 11 ) 12 13 var ( 14 // App settings. 15 AppVer string 16 AppName string 17 AppUrl string 18 AppSubUrl string 19 AppPath = utils.AppPath() 20 AppFilePath = utils.AppFilePath() 21 AppDir = utils.AppDir() 22 AppModuleDir = "module" 23 defaultConfig = New(DEFAULT_PREFIX) 24 cfgs sync.Map 25 ) 26 27 type ( 28 Option func(*Config) 29 30 core struct { 31 name string 32 fmt *format 33 models sync.Map 34 FileName string 35 Mode ModeType 36 } 37 38 Config struct { 39 //name string 40 //fmt *format 41 //models sync.Map 42 AutoCreateFile bool `field:"-"` 43 //Mode ModeType 44 //FileName string 45 Debug bool 46 core *core // 配置文件核心 为了支持继承nil指针问题 47 changed bool 48 } 49 50 IConfig interface { 51 String() string // the Prefix name 52 Load() error 53 Save(immed ...bool) error // immed mean save to file immediately or not. 54 } 55 56 iConfig interface { 57 checkSelf(c *Config, cfg IConfig) // 检测自己是否被赋值 58 } 59 ) 60 61 /* 62 func init() { 63 AppFilePath = utils.AppFilePath() 64 AppPath = utils.AppPath() 65 AppDir = utils.AppDir() 66 } 67 */ 68 69 func Default() *Config { 70 return defaultConfig 71 } 72 73 func Init(opts ...Option) { 74 defaultConfig.Init(opts...) 75 } 76 77 func Register(cfg IConfig) { 78 defaultConfig.Register(cfg) 79 } 80 81 func Unregister(cfg IConfig) { 82 defaultConfig.Unregister(cfg) 83 } 84 85 func Load(fileName ...string) error { 86 return defaultConfig.LoadFromFile(fileName...) 87 } 88 89 func New(name string, opts ...Option) *Config { 90 // 取缓存 91 var c *core 92 if c, ok := cfgs.Load(name); ok { 93 c = c.(*core) 94 } else { 95 c = &core{ 96 fmt: newFormat(), // 配置主要文件格式读写实现, 97 FileName: CONFIG_FILE_NAME, 98 Mode: MODE_NORMAL, 99 name: name, 100 } 101 cfgs.Store(name, c) 102 } 103 104 cfg := &Config{ 105 core: c, 106 AutoCreateFile: true, 107 changed: false, 108 } 109 // 初始化程序硬配置 110 cfg.Init(opts...) 111 // 加载文件配置 112 cfg.LoadFromFile() 113 114 return cfg 115 } 116 117 func (self *Config) Core() *core { 118 if self.core == nil { 119 c, ok := cfgs.Load(DEFAULT_PREFIX) 120 if ok { 121 self.core = c.(*core) 122 } 123 } 124 125 return self.core 126 } 127 128 // 注册添加其他配置 129 func (self *Config) Register(cfg IConfig) { 130 cfgStr := cfg.String() 131 if cfgStr == "" { 132 return 133 } 134 135 core := self.Core() 136 137 if !core.fmt.v.InConfig(cfgStr) { 138 if cfgStr == "registry." { 139 log.Println(cfgStr) 140 } 141 142 // 保存配置到core 143 err := cfg.Save() 144 if err != nil { 145 log.Fatal(err) 146 } 147 148 // 保存配置到文件 149 err = self.SaveToFile() 150 if err != nil { 151 log.Fatal(err) 152 } 153 } 154 155 // 直接覆盖 156 core.models.Store(cfgStr, cfg) 157 158 // 加载配置 159 if err := cfg.Load(); err != nil { 160 log.Fatalf("load %v config failed!", cfgStr) 161 } 162 } 163 164 func (self *Config) Unregister(cfg IConfig) { 165 self.Core().models.Delete(cfg.String()) 166 } 167 168 // config: the config struct with binding the options 169 func (self *Config) Init(opts ...Option) { 170 self.Core() 171 172 for _, opt := range opts { 173 opt(self) 174 } 175 } 176 177 func (self *Config) Reload() { 178 // 重新加载配置 179 self.Core().models.Range(func(key any, value any) bool { 180 v := value.(IConfig) 181 err := v.Load() 182 if err != nil { 183 log.Fatalf("reload %v config failed!", key) 184 } 185 return true 186 }) 187 } 188 189 // 检测配置路径是否在Config里出现了 190 func (self *Config) InConfig(path string) bool { 191 return self.Core().fmt.v.InConfig(path) 192 } 193 194 func (self *Config) LoadFromFile(fileName ...string) error { 195 core := self.Core() 196 197 if core.FileName == "" { 198 core.FileName = CONFIG_FILE_NAME 199 } 200 filePath := filepath.Join(AppPath, core.FileName) 201 core.fmt.v.SetConfigFile(filePath) 202 203 fileExists := utils.FileExists(filePath) && self.AutoCreateFile 204 205 // Find and read the config file 206 // Handle errors reading the config file 207 if fileExists { 208 err := core.fmt.v.ReadInConfig() 209 if err != nil { 210 return err 211 } 212 } 213 214 // 校正 215 // 保存默认配置 216 core.models.Range(func(key any, value any) bool { 217 if v, ok := value.(IConfig); ok { 218 if key != v.String() { 219 // 配置路径被更改过 220 core.models.Delete(key) 221 core.models.Store(v.String(), v) 222 } 223 } 224 return true 225 }) 226 227 changed := 0 228 core.models.Range(func(key any, value any) bool { 229 if v, ok := value.(IConfig); ok { 230 if !fileExists || !core.fmt.v.InConfig(v.String()) { 231 // 没有配置文件则保存默认配置 232 if err := v.Save(false); err != nil { 233 log.Fatalf("save %v config failed!", v.String()) 234 return false 235 } 236 changed++ 237 } else { 238 if err := v.Load(); err != nil { 239 log.Fatalf("save %v config failed!", key) 240 } 241 } 242 243 } 244 return true 245 }) 246 247 if changed > 0 { 248 // 保存新的配置 249 return core.fmt.v.WriteConfig() 250 } 251 252 return nil 253 } 254 255 func (self *Config) LoadToModel(model IConfig) error { 256 core := self.Core() 257 258 // 如果配置不存于V 259 if !core.fmt.v.InConfig(model.String()) { 260 err := model.Save() 261 if err != nil { 262 return err 263 } 264 } else { 265 err := core.fmt.UnmarshalKey(model.String(), model) 266 if err != nil { 267 return err 268 } 269 } 270 271 // 保存但不覆盖注册的Model 272 if _, has := core.models.Load(model.String()); !has { 273 self.Register(model) 274 } 275 return nil 276 } 277 278 func (self *Config) SaveToFile(opts ...Option) error { 279 core := self.Core() 280 281 for _, opt := range opts { 282 opt(self) 283 } 284 285 if core.FileName == "" { 286 core.FileName = CONFIG_FILE_NAME 287 } 288 289 core.fmt.v.SetConfigFile(filepath.Join(AppPath, core.FileName)) 290 return core.fmt.v.WriteConfig() 291 } 292 293 // 从数据类型加载数据 294 // 只支持map[string]any 和struct 295 func (self *Config) SaveFromModel(model IConfig, immed ...bool) error { 296 opts := utils.Struct2ItfMap(model) 297 298 for k, v := range opts { 299 // 过滤自己 300 if strings.ToLower("config") == strings.ToLower(k) { 301 continue 302 } 303 304 self.SetValue(strings.Join([]string{model.String(), k}, "."), v) 305 } 306 307 if len(immed) > 0 { 308 // 立即保存 309 on := immed[0] 310 if on { 311 return self.SaveToFile() 312 } 313 } 314 315 return nil 316 } 317 318 func (self *Config) GetBool(field string, defaultValue bool) bool { 319 return self.Core().fmt.GetBool(field, defaultValue) 320 } 321 322 // GetStringValue from default namespace 323 func (self *Config) GetString(field, defaultValue string) string { 324 return self.Core().fmt.GetString(field, defaultValue) 325 } 326 327 // GetIntValue from default namespace 328 func (self *Config) GetInt(field string, defaultValue int) int { 329 return self.Core().fmt.GetInt(field, defaultValue) 330 } 331 332 func (self *Config) GetInt32(field string, defaultValue int32) int32 { 333 return self.Core().fmt.GetInt32(field, defaultValue) 334 } 335 336 func (self *Config) GetInt64(field string, defaultValue int64) int64 { 337 return self.Core().fmt.GetInt64(field, defaultValue) 338 } 339 340 func (self *Config) GetIntSlice(field string, defaultValue []int) []int { 341 return self.Core().fmt.GetIntSlice(field, defaultValue) 342 } 343 344 func (self *Config) GetTime(field string, defaultValue time.Time) time.Time { 345 return self.Core().fmt.GetTime(field, defaultValue) 346 } 347 348 func (self *Config) GetDuration(field string, defaultValue time.Duration) time.Duration { 349 return self.Core().fmt.GetDuration(field, defaultValue) 350 } 351 352 func (self *Config) GetFloat64(field string, defaultValue float64) float64 { 353 return self.Core().fmt.GetFloat64(field, defaultValue) 354 } 355 356 func (self *Config) SetValue(field string, value interface{}) { 357 self.Core().fmt.SetValue(field, value) 358 } 359 360 func (self *Config) xUnmarshal(rawVal interface{}) error { 361 return self.Core().fmt.Unmarshal(rawVal) 362 } 363 364 // 反序列字段映射到数据类型 365 func (self *Config) xUnmarshalField(field string, rawVal interface{}) error { 366 return self.Core().fmt.UnmarshalKey(field, rawVal) 367 }