package config import ( "fmt" "io/ioutil" "log" "os" "path/filepath" "sync" "encoding/json" "git.pyer.club/kingecg/gologger" "github.com/fsnotify/fsnotify" "gopkg.in/yaml.v2" ) // Config 系统配置结构体 type Config struct { Server ServerConfig `yaml:"server" json:"server"` Storage StorageConfig `yaml:"storage" json:"storage"` Log gologger.LoggersConfig `yaml:"log" json:"log"` } // ServerConfig 服务器配置 type ServerConfig struct { Host string `yaml:"host" json:"host"` Port int `yaml:"port" json:"port"` } // StorageConfig 存储配置 type StorageConfig struct { Engine string `yaml:"engine" json:"engine"` DataPath string `yaml:"dataPath" json:"dataPath"` } var ( configInstance *Config once sync.Once watcher *fsnotify.Watcher // 配置文件监视器 ) // NewDefaultConfig 创建默认配置 func NewDefaultConfig() *Config { return &Config{ Server: ServerConfig{ Host: "0.0.0.0", Port: 27017, }, Storage: StorageConfig{ Engine: "memory", DataPath: "/var/lib/goaidb", }, Log: gologger.LoggersConfig{ Appenders: map[string]gologger.LogAppenderConfig{ "console": { Type: "console", Formatter: "text", Options: map[string]interface{}{}, }, }, Categories: map[string]gologger.LogConfig{ "default": { Appenders: []string{"console"}, }, }, }, } } // ParseConfig 解析配置文件 // 支持JSON和YAML格式 // 返回解析后的配置对象和错误信息 func ParseConfig(filePath string) (*Config, error) { // 检查文件是否存在 if _, err := os.Stat(filePath); os.IsNotExist(err) { return nil, fmt.Errorf("配置文件不存在: %s", filePath) } // 读取文件内容 data, err := ioutil.ReadFile(filePath) if err != nil { return nil, fmt.Errorf("读取配置文件失败: %v", err) } // 根据文件扩展名选择解析方式 var cfg Config switch filepath.Ext(filePath) { case ".json": if err := json.Unmarshal(data, &cfg); err != nil { return nil, fmt.Errorf("JSON解析失败: %v", err) } case ".yaml", ".yml": if err := yaml.Unmarshal(data, &cfg); err != nil { return nil, fmt.Errorf("YAML解析失败: %v", err) } default: return nil, fmt.Errorf("不支持的配置文件格式") } return &cfg, nil } // ValidateConfig 验证配置有效性 // 返回验证结果和第一个发现的错误(如果有) func (c *Config) Validate() (bool, error) { // 验证服务器配置 if c.Server.Port < 1024 || c.Server.Port > 65535 { return false, fmt.Errorf("端口必须在1024-65535之间: %d", c.Server.Port) } // 验证存储配置 if c.Storage.Engine != "memory" && c.Storage.Engine != "rocksdb" { return false, fmt.Errorf("不支持的存储引擎: %s", c.Storage.Engine) } // 验证数据路径是否存在 if _, err := os.Stat(c.Storage.DataPath); os.IsNotExist(err) { return false, fmt.Errorf("数据目录不存在: %s", c.Storage.DataPath) } return true, nil } // WatchConfig 监听配置文件变化并自动重载 func WatchConfig(filePath string) error { // 创建文件监视器 w, err := fsnotify.NewWatcher() if err != nil { return fmt.Errorf("创建文件监视器失败: %v", err) } // 添加文件监视 dir := filepath.Dir(filePath) fileName := filepath.Base(filePath) err = w.Add(dir) if err != nil { return fmt.Errorf("添加文件监视失败: %v", err) } // 启动监听协程 go func() { for { select { case event, ok := <-w.Events: if !ok { return } // 当配置文件被修改或创建时重新加载 if (event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Create == fsnotify.Create) && filepath.Base(event.Name) == fileName { // 重新加载配置 newCfg, err := ParseConfig(filePath) if err != nil { log.Printf("配置重载失败: %v", err) continue } // 更新全局配置 SetGlobalConfig(newCfg) log.Printf("配置已更新") } case err, ok := <-w.Errors: if !ok { return } log.Printf("文件监视错误: %v", err) } } }() watcher = w return nil } // CloseWatcher 关闭配置文件监视器 func CloseWatcher() { if watcher != nil { watcher.Close() } } // GetConfig 获取全局配置实例 func GetConfig() *Config { once.Do(func() { configInstance = NewDefaultConfig() }) return configInstance } // SetGlobalConfig 设置全局配置实例 func SetGlobalConfig(cfg *Config) { once.Do(func() { configInstance = cfg }) }