This commit is contained in:
2025-11-19 01:28:34 +03:00
parent 469879cfd9
commit 1b9bb09ca4
12 changed files with 659 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
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)