package config import ( "fmt" "os" "path/filepath" "gopkg.in/yaml.v3" ) type Config struct { Server struct { Port int `yaml:"port"` } `yaml:"server"` Backend struct { URL string `yaml:"url"` } `yaml:"backend"` Heartbeat struct { Interval int `yaml:"interval"` // 心跳间隔(秒) } `yaml:"heartbeat"` Log struct { File string `yaml:"file"` // 日志文件路径(空则输出到标准错误) Level string `yaml:"level"` // 日志级别:debug, info, warn, error(默认: info) } `yaml:"log"` Debug bool `yaml:"debug"` // 节点信息(通过心跳获取并持久化) Node struct { ID uint `yaml:"id"` // 节点ID IP string `yaml:"ip"` // 节点外网IP Country string `yaml:"country"` // 国家 Province string `yaml:"province"` // 省份 City string `yaml:"city"` // 城市 ISP string `yaml:"isp"` // ISP } `yaml:"node"` } func Load() (*Config, error) { cfg := &Config{} // 默认配置 cfg.Server.Port = 2200 cfg.Heartbeat.Interval = 60 cfg.Debug = false // 默认日志配置 logFile := os.Getenv("LOG_FILE") if logFile == "" { logFile = "node.log" } cfg.Log.File = logFile cfg.Log.Level = "info" // 尝试从配置文件读取 configPath := os.Getenv("CONFIG_PATH") if configPath == "" { configPath = "config.yaml" } if _, err := os.Stat(configPath); err == nil { data, err := os.ReadFile(configPath) if err != nil { return nil, fmt.Errorf("读取配置文件失败: %w", err) } if err := yaml.Unmarshal(data, cfg); err != nil { return nil, fmt.Errorf("解析配置文件失败: %w", err) } } // 环境变量优先级最高,覆盖配置文件中的设置 // 支持 BACKEND_URL 环境变量覆盖后端地址 if backendURL := os.Getenv("BACKEND_URL"); backendURL != "" { cfg.Backend.URL = backendURL } // 如果配置文件中没有设置日志文件,使用环境变量或默认值 if cfg.Log.File == "" { logFile := os.Getenv("LOG_FILE") if logFile == "" { logFile = "node.log" } cfg.Log.File = logFile } // 如果配置文件中没有设置日志级别,使用默认值 if cfg.Log.Level == "" { if cfg.Debug { cfg.Log.Level = "debug" } else { cfg.Log.Level = "info" } } return cfg, nil } // Save 保存配置到文件 func (c *Config) Save() error { configPath := os.Getenv("CONFIG_PATH") if configPath == "" { configPath = "config.yaml" } // 确保目录存在 dir := filepath.Dir(configPath) if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("创建配置目录失败: %w", err) } data, err := yaml.Marshal(c) if err != nil { return fmt.Errorf("序列化配置失败: %w", err) } if err := os.WriteFile(configPath, data, 0644); err != nil { return fmt.Errorf("写入配置文件失败: %w", err) } return nil } // GetConfigPath 获取配置文件路径 func GetConfigPath() string { configPath := os.Getenv("CONFIG_PATH") if configPath == "" { configPath = "config.yaml" } return configPath }