Что делать, если нельзя писать логи внутри функции fetch, а можно только в функции main?
Что проверяют
Понимаете ли вы, что логирование это побочный эффект, а не часть работы функции, и умеете ли развязать нижний слой с тем, кто решает, куда писать. Заодно проверяют, тянете ли вы глобальный логгер в каждый пакет.
Как отвечать
Сначала уточните смысл ограничения: обычно оно означает, что fetch это переиспользуемый слой, у которого нет права решать, что и куда печатать. Отсюда решение: функция не логирует, она возвращает то, из чего вызывающий сам соберёт запись.
- ошибка с контекстом через обёртку
fmt.Errorf("fetch %s: %w", url, err), дальшеerrors.Isиerrors.Asвmain; - результат с деталями: код ответа, число попыток, длительность, а
mainуже решает, это уровеньInfoилиWarn; - зависимость параметром, если логи всё же нужны внутри: узкий интерфейс, объявленный на стороне потребителя, или
*slog.Loggerаргументом послеctx.
Сквозные поля удобно нести в context.Context: вызов вида slog.InfoContext(ctx, ...) отдаёт контекст обработчику, и тот подмешивает идентификатор запроса без лишних параметров в сигнатуре.
func fetch(ctx context.Context, url string) (Result, error) {
resp, err := http.DefaultClient.Do(req)
if err != nil {
return Result{}, fmt.Errorf("fetch %s: %w", url, err)
}
defer resp.Body.Close()
return parse(resp)
}Скажите вслух главное правило: либо логируем, либо возвращаем ошибку, но не то и другое сразу, иначе один сбой оставит три одинаковые строки на разных уровнях.
Где спотыкаются
Заводят пакетный var log = ... и считают вопрос закрытым. Глобальный логгер нельзя подменить в тесте, он привязывает библиотеку к формату вывода приложения и мешает параллельным тестам.
Второе: передают func(string) вместо логгера. Уровни, поля и возможность отключить вывод при этом теряются, а строку приходится склеивать на каждом вызове, даже когда она никому не нужна.
Третье: зовут log.Fatal или panic внутри нижней функции. Завершение процесса это решение владельца, а не того, кто сходил по сети: Fatal вызывает os.Exit, и отложенные функции не выполняются.