package config import ( "fmt" "log/slog" "net/url" "os" "strconv" "strings" "time" ) // Универсальная функция получения значения из окружения с парсером. func GetEnvAs[T any](key string, defaultVal T, parse func(string) (T, error)) T { raw, ok := os.LookupEnv(key) if !ok || strings.TrimSpace(raw) == "" { return defaultVal } v, err := parse(raw) if err != nil { // одна строка лога достаточно — не дублируем slog.Warn(fmt.Sprintf("cannot parse env %q, using default", key), "key", key, "raw", raw, "default", defaultVal, "error", err) return defaultVal } return v } /* ====== БАЗОВЫЕ АДАПТЕРЫ ====== */ func ParseString(s string) (string, error) { // просто возвращаем trimmed string return strings.TrimSpace(s), nil } func ParseBool(s string) (bool, error) { return strconv.ParseBool(strings.TrimSpace(s)) } func ParseInt(s string) (int, error) { i64, err := strconv.ParseInt(strings.TrimSpace(s), 10, 0) return int(i64), err } func ParseInt64(s string) (int64, error) { return strconv.ParseInt(strings.TrimSpace(s), 10, 64) } func ParseUint(s string) (uint, error) { u64, err := strconv.ParseUint(strings.TrimSpace(s), 10, 0) return uint(u64), err } func ParseFloat64(s string) (float64, error) { return strconv.ParseFloat(strings.TrimSpace(s), 64) } func ParseDuration(s string) (time.Duration, error) { // поддерживает "150ms", "2s", "1m", "24h" return time.ParseDuration(strings.TrimSpace(s)) } func ParseTimeRFC3339(s string) (time.Time, error) { return time.Parse(time.RFC3339, strings.TrimSpace(s)) } func ParseURL(s string) (*url.URL, error) { return url.Parse(strings.TrimSpace(s)) } /* ====== СПИСКИ (CSV/SEPARATOR) ====== */ // Универсальный адаптер для списков с произвольным парсером элемента. func MakeListParser[T any](sep string, itemParser func(string) (T, error)) func(string) ([]T, error) { return func(s string) ([]T, error) { s = strings.TrimSpace(s) if s == "" { var zero []T return zero, nil } parts := strings.Split(s, sep) out := make([]T, 0, len(parts)) for _, p := range parts { v, err := itemParser(p) if err != nil { return nil, fmt.Errorf("cannot parse list item %q: %w", p, err) } out = append(out, v) } return out, nil } } // Частые случаи: var ParseCSVStrings = MakeListParser[string](",", ParseString) var ParseCSVInts = MakeListParser[int](",", ParseInt) var ParseCSVFloat64 = MakeListParser[float64](",", ParseFloat64)