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  }