package config import ( "fmt" "sync" "github.com/BurntSushi/toml" "github.com/fsnotify/fsnotify" "go.uber.org/zap" ) // Config 应用配置结构 type Config struct { Server ServerConfig `toml:"server"` Log LogConfig `toml:"log"` Protocol ProtocolConfig `toml:"protocol"` } // ServerConfig 服务器配置 type ServerConfig struct { Host string `toml:"host"` Port int `toml:"port"` } // LogConfig 日志配置 type LogConfig struct { Level string `toml:"level"` Output string `toml:"output"` MaxSize int `toml:"max_size"` MaxBackups int `toml:"max_backups"` MaxAge int `toml:"max_age"` } // ProtocolConfig 协议配置 type ProtocolConfig struct { Name string `toml:"name"` Version string `toml:"version"` Options map[string]string `toml:"options"` } // ConfigManager 配置管理器 type ConfigManager struct { configPath string config *Config logger *zap.Logger mu sync.RWMutex callbacks []func(*Config) } // NewConfigManager 创建配置管理器 func NewConfigManager(configPath string, logger *zap.Logger) *ConfigManager { return &ConfigManager{ configPath: configPath, logger: logger, callbacks: make([]func(*Config), 0), } } // Load 加载配置文件 func (cm *ConfigManager) Load() error { cm.mu.Lock() defer cm.mu.Unlock() var cfg Config if _, err := toml.DecodeFile(cm.configPath, &cfg); err != nil { return fmt.Errorf("failed to decode config: %w", err) } cm.config = &cfg cm.logger.Info("Config loaded successfully", zap.String("path", cm.configPath), zap.String("server", fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port)), ) // 触发回调 for _, cb := range cm.callbacks { cb(cm.config) } return nil } // Get 获取当前配置 func (cm *ConfigManager) Get() *Config { cm.mu.RLock() defer cm.mu.RUnlock() return cm.config } // Reload 重新加载配置 func (cm *ConfigManager) Reload() error { return cm.Load() } // RegisterCallback 注册配置变更回调 func (cm *ConfigManager) RegisterCallback(callback func(*Config)) { cm.mu.Lock() defer cm.mu.Unlock() cm.callbacks = append(cm.callbacks, callback) } // Watch 监听配置文件变化 func (cm *ConfigManager) Watch() error { watcher, err := fsnotify.NewWatcher() if err != nil { return fmt.Errorf("failed to create watcher: %w", err) } if err := watcher.Add(cm.configPath); err != nil { return fmt.Errorf("failed to watch config file: %w", err) } go func() { for { select { case event, ok := <-watcher.Events: if !ok { return } if event.Op&fsnotify.Write == fsnotify.Write { cm.logger.Info("Config file changed, reloading...", zap.String("file", event.Name)) if err := cm.Reload(); err != nil { cm.logger.Error("Failed to reload config", zap.Error(err)) } } case err, ok := <-watcher.Errors: if !ok { return } cm.logger.Error("Watcher error", zap.Error(err)) } } }() return nil } // Close 关闭配置管理器 func (cm *ConfigManager) Close() error { return nil }