94 lines
2.0 KiB
Go
94 lines
2.0 KiB
Go
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
|
||
}
|