package config import ( "os" "strconv" "gopkg.in/yaml.v3" ) type Config struct { HTTP struct { Addr string `yaml:"addr"` } `yaml:"http"` Database struct { DSN string `yaml:"dsn"` MaxOpenConns int `yaml:"max_open_conns"` MaxIdleConns int `yaml:"max_idle_conns"` } `yaml:"database"` Redis struct { Addr string `yaml:"addr"` TTLSeconds int `yaml:"ttl_seconds"` } `yaml:"redis"` JWT struct { Secret string `yaml:"secret"` TTLMinutes int `yaml:"ttl_minutes"` } `yaml:"jwt"` RateLimit struct { RequestsPerMinute int `yaml:"requests_per_minute"` } `yaml:"rate_limit"` Email struct { Endpoint string `yaml:"endpoint"` } `yaml:"email"` } func Load() (Config, error) { path := getenv("APP_CONFIG", "config.yaml") data, err := os.ReadFile(path) if err != nil { return Config{}, err } var cfg Config if err := yaml.Unmarshal(data, &cfg); err != nil { return Config{}, err } override(&cfg) return cfg, nil } func override(cfg *Config) { if v := os.Getenv("HTTP_ADDR"); v != "" { cfg.HTTP.Addr = v } if v := os.Getenv("DB_DSN"); v != "" { cfg.Database.DSN = v } if v := os.Getenv("REDIS_ADDR"); v != "" { cfg.Redis.Addr = v } if v := os.Getenv("JWT_SECRET"); v != "" { cfg.JWT.Secret = v } if v := os.Getenv("RATE_LIMIT_RPM"); v != "" { if n, err := strconv.Atoi(v); err == nil { cfg.RateLimit.RequestsPerMinute = n } } } func getenv(key, fallback string) string { if v := os.Getenv(key); v != "" { return v } return fallback }