package config import ( "encoding/json" "fmt" "os" "sync" "time" ) // Config 应用配置 type Config struct { Server ServerConfig `json:"server"` Monitor MonitorConfig `json:"monitor"` DataPath string `json:"data_path"` } // ServerConfig 服务器配置 type ServerConfig struct { Port string `json:"port"` Host string `json:"host"` } // MonitorConfig 监控配置 type MonitorConfig struct { Interval time.Duration `json:"interval"` // 检测间隔 Timeout time.Duration `json:"timeout"` // 请求超时时间 RetryCount int `json:"retry_count"` // 重试次数 HistoryDays int `json:"history_days"` // 保留历史天数 } var ( cfg *Config once sync.Once ) // GetConfig 获取配置单例 func GetConfig() *Config { once.Do(func() { cfg = &Config{ Server: ServerConfig{ Port: getEnv("SERVER_PORT", "8080"), Host: getEnv("SERVER_HOST", "0.0.0.0"), }, Monitor: MonitorConfig{ Interval: parseDuration(getEnv("MONITOR_INTERVAL", "5m"), 5*time.Minute), Timeout: parseDuration(getEnv("MONITOR_TIMEOUT", "10s"), 10*time.Second), RetryCount: parseInt(getEnv("MONITOR_RETRY_COUNT", "3"), 3), HistoryDays: parseInt(getEnv("MONITOR_HISTORY_DAYS", "7"), 7), }, DataPath: getEnv("DATA_PATH", "./data"), } // 尝试从配置文件加载(会覆盖环境变量配置) loadConfigFromFile() }) return cfg } // getEnv 获取环境变量,如果不存在则返回默认值 func getEnv(key, defaultValue string) string { if value := os.Getenv(key); value != "" { return value } return defaultValue } // parseInt 解析整数环境变量 func parseInt(value string, defaultValue int) int { if value == "" { return defaultValue } var result int if _, err := fmt.Sscanf(value, "%d", &result); err != nil { return defaultValue } return result } // parseDuration 解析时间间隔环境变量 func parseDuration(value string, defaultValue time.Duration) time.Duration { if value == "" { return defaultValue } if duration, err := time.ParseDuration(value); err == nil { return duration } return defaultValue } // loadConfigFromFile 从文件加载配置 func loadConfigFromFile() { configFile := "./data/config.json" if _, err := os.Stat(configFile); os.IsNotExist(err) { return } data, err := os.ReadFile(configFile) if err != nil { return } var fileCfg struct { Server ServerConfig `json:"server"` Monitor struct { IntervalMinutes int `json:"interval_minutes"` TimeoutSeconds int `json:"timeout_seconds"` RetryCount int `json:"retry_count"` HistoryDays int `json:"history_days"` } `json:"monitor"` DataPath string `json:"data_path"` } if err := json.Unmarshal(data, &fileCfg); err != nil { return } if fileCfg.Server.Port != "" { cfg.Server.Port = fileCfg.Server.Port } if fileCfg.Server.Host != "" { cfg.Server.Host = fileCfg.Server.Host } if fileCfg.Monitor.IntervalMinutes > 0 { cfg.Monitor.Interval = time.Duration(fileCfg.Monitor.IntervalMinutes) * time.Minute } if fileCfg.Monitor.TimeoutSeconds > 0 { cfg.Monitor.Timeout = time.Duration(fileCfg.Monitor.TimeoutSeconds) * time.Second } if fileCfg.Monitor.RetryCount > 0 { cfg.Monitor.RetryCount = fileCfg.Monitor.RetryCount } if fileCfg.Monitor.HistoryDays > 0 { cfg.Monitor.HistoryDays = fileCfg.Monitor.HistoryDays } if fileCfg.DataPath != "" { cfg.DataPath = fileCfg.DataPath } } // SaveConfig 保存配置到文件 func SaveConfig() error { configFile := cfg.DataPath + "/config.json" fileCfg := struct { Server ServerConfig `json:"server"` Monitor struct { IntervalMinutes int `json:"interval_minutes"` TimeoutSeconds int `json:"timeout_seconds"` RetryCount int `json:"retry_count"` HistoryDays int `json:"history_days"` } `json:"monitor"` DataPath string `json:"data_path"` }{ Server: cfg.Server, Monitor: struct { IntervalMinutes int `json:"interval_minutes"` TimeoutSeconds int `json:"timeout_seconds"` RetryCount int `json:"retry_count"` HistoryDays int `json:"history_days"` }{ IntervalMinutes: int(cfg.Monitor.Interval.Minutes()), TimeoutSeconds: int(cfg.Monitor.Timeout.Seconds()), RetryCount: cfg.Monitor.RetryCount, HistoryDays: cfg.Monitor.HistoryDays, }, DataPath: cfg.DataPath, } data, err := json.MarshalIndent(fileCfg, "", " ") if err != nil { return err } return os.WriteFile(configFile, data, 0644) }