package config import ( "fmt" "os" "path/filepath" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/spf13/viper" ) // Load 从文件和环境变量加载配置 func Load() (*Config, error) { // 确定配置路径 configPath := os.Getenv(constants.EnvConfigPath) if configPath == "" { configPath = constants.DefaultConfigPath } // 检查环境特定配置(dev, staging, prod) configEnv := os.Getenv(constants.EnvConfigEnv) if configEnv != "" { // 优先尝试环境特定配置 envConfigPath := fmt.Sprintf("configs/config.%s.yaml", configEnv) if _, err := os.Stat(envConfigPath); err == nil { configPath = envConfigPath } } // 设置 Viper viper.SetConfigFile(configPath) viper.SetConfigType("yaml") // 启用环境变量覆盖 viper.AutomaticEnv() viper.SetEnvPrefix("APP") // 读取配置文件 if err := viper.ReadInConfig(); err != nil { return nil, fmt.Errorf("failed to read config file: %w", err) } // 反序列化到 Config 结构体 cfg := &Config{} if err := viper.Unmarshal(cfg); err != nil { return nil, fmt.Errorf("failed to unmarshal config: %w", err) } // 验证配置 if err := cfg.Validate(); err != nil { return nil, err } // 设为全局配置 globalConfig.Store(cfg) return cfg, nil } // Reload 重新加载当前配置文件 func Reload() (*Config, error) { if err := viper.ReadInConfig(); err != nil { return nil, fmt.Errorf("failed to reload config: %w", err) } cfg := &Config{} if err := viper.Unmarshal(cfg); err != nil { return nil, fmt.Errorf("failed to unmarshal config: %w", err) } // 设置前验证 if err := cfg.Validate(); err != nil { return nil, err } // 原子交换 globalConfig.Store(cfg) return cfg, nil } // GetConfigPath 返回当前已加载配置文件的绝对路径 func GetConfigPath() string { configFile := viper.ConfigFileUsed() if configFile == "" { return "" } absPath, err := filepath.Abs(configFile) if err != nil { return configFile } return absPath }