👨💻Структурное логирование в Go через slog — 22 июня 2026 г. в 07:00:07.520
👨💻Структурное логирование в Go через slog До версии 1.21 в Go не было единого подхода к логированию. Команды выбирали между сторонними библиотеками вроде zap, logrus и zerolog, поэтому кодовая база разных проектов выглядела неодинаково. Стандартный пакет log умел писать только обычные текстовые строки, которые тяжело парсить и собирать в системах вроде Loki или ELK. В Go 1.21 появился slog, который принёс структурное логирование прямо в стандартную библиотеку. Если из всего списка новинок вы захотите взять только одну, берите эту. Какую боль решает Структурные логи это пары ключ значение, а не склеенная строка. Их легко фильтровать, искать по конкретным полям и отдавать в JSON прямо в систему сбора. Раньше ради этого приходилось тянуть внешнюю зависимость, теперь хватает стандартной библиотеки. Старый способ выглядел так: log.Printf("[ERROR] User %d login failed from IP %s", userID, ip) Здесь данные смешаны с текстом, и чтобы вытащить userID, нужно писать регулярки. Современный способ: import "log/slog" slog.Error("Login failed", "userID", userID, "ip", ip) Сообщение остаётся читаемым, а данные лежат в отдельных полях. Что он делает slog строится вокруг трёх частей. Logger принимает вызовы вроде Info и Error. Handler решает, куда и в каком формате писать. Attr это пара ключ значение. В комплекте идут два обработчика, TextHandler для человекочитаемого вывода и JSONHandler для машинного. Как настроить JSON вывод Чтобы получать логи в JSON, достаточно подменить обработчик у глобального логгера: logger := slog.New (slog.NewJSONHandler(os.Stdout, nil)) slog.SetDefault(logger) slog.Info ("server started", "port", 8080) На выходе получится строка JSON с полями time, level, msg и port. Её сразу можно отправлять в сборщик логов без дополнительной обработки. Группировка и контекст Часто к каждому запросу удобно прикреплять одни и те же поля. Метод With создаёт логгер с заранее заданными атрибутами: reqLogger := slog.With("requestID", reqID, "userID", userID) reqLogger.Info ("processing request") reqLogger.Warn("slow response", "ms", 320) Теперь requestID и userID попадут в каждую запись без повторного перечисления. Переводить проект можно постепенно, начав с замены log на slog в новых модулях. Старый код при этом продолжит работать, а новые записи сразу станут пригодными для машинного разбора.

