> Как понять, что код отработал правильно (Go)
Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы
Компании: Ozon
Стек: Go
> Пример ответа
Короткий ответ
Понять, что код отработал правильно, можно через комбинацию проверок: явные возвращаемые ошибки, логирование ключевых этапов, метрики и observability, а также тесты (unit, integration, e2e). В Go особенно важно не игнорировать error-значения и проверять их сразу после вызова. Для долгоиграющих процессов нужны health checks и алерты. Правильность - это не только отсутствие паники, но и соответствие ожидаемому поведению системы в целом.
Подробное объяснение
Правильность выполнения кода в Go складывается из нескольких уровней:
-
Контракт функции - функция возвращает ожидаемый результат или ошибку. В Go это явно:
if err != nilпосле каждого вызова, который может завершиться неудачей. Если функция не возвращает ошибку, но может упасть - это нарушение контракта. -
Состояние системы - после выполнения кода внешние зависимости (БД, кэш, очередь) должны находиться в ожидаемом состоянии. Проверяется через интеграционные тесты и ручную проверку в staging.
-
Побочные эффекты - запись в лог, отправка метрик, изменение конфигурации. Они должны происходить ровно столько раз, сколько ожидается (идемпотентность, отсутствие дублей).
-
Производительность и ресурсы - код не должен утекать по памяти, горутинам, соединениям. Проверяется через
pprof,go test -race, нагрузочное тестирование. -
Наблюдаемость - в production правильность определяется через метрики (latency, error rate, saturation) и трейсы. Если метрики в норме и алерты не срабатывают - код работает правильно.
Для фоновых задач (worker, consumer) важно иметь механизм подтверждения успешного завершения: запись в отдельную таблицу, отправка heartbeat, завершение с кодом 0.
На практике
В реальной работе правильность проверяется так:
- Локально:
go test ./...,go vet,staticcheck, запуск с-race. - В CI: тесты, линтеры, проверка покрытия, сборка.
- В staging: ручное тестирование сценариев, проверка логов и метрик.
- В production: мониторинг ключевых метрик, алерты на ошибки, дашборды.
Для long-running процессов (например, HTTP-сервер) правильность - это стабильный uptime, корректные ответы на health check, отсутствие 5xx. Для batch-задач - успешный exit code и запись результата в хранилище.
Важно различать "код выполнился без ошибок" и "код сделал то, что нужно". Второе проверяется только через бизнес-логику и тесты на неё.
Пример кода
GOfunc ProcessOrder(ctx context.Context, orderID string) error {// 1. Валидация входных данныхif orderID == "" {return errors.New("empty order id")}// 2. Вызов с проверкой ошибкиorder, err := repo.GetOrder(ctx, orderID)if err != nil {return fmt.Errorf("get order: %w", err)}// 3. Бизнес-логика с явной проверкойif order.Status != "pending" {return fmt.Errorf("order %s already processed", orderID)}// 4. Побочный эффект с подтверждениемif err := repo.MarkProcessed(ctx, orderID); err != nil {return fmt.Errorf("mark processed: %w", err)}// 5. Логирование успеха для observabilitylogger.Info("order processed", "order_id", orderID)return nil}
Правильность здесь определяется: ошибка возвращается на каждом шаге, успех логируется, состояние БД меняется только после всех проверок.
Как отвечать на собеседовании
Начните с базового: "правильность - это соответствие ожидаемому поведению, а не просто отсутствие ошибок". Затем перечислите уровни проверки: ошибки, тесты, метрики, логи. Подчеркните специфику Go: явная обработка ошибок, defer для cleanup, context для отмены. Приведите пример из практики, где код формально работал, но делал не то (например, гонка данных или потерянный error). Завершите мыслью о том, что в production правильность - это непрерывный процесс наблюдения, а не разовая проверка.
Что проверяет интервьюер
Интервьюер оценивает:
- Понимание, что ошибки в Go - это значения, и их нельзя игнорировать.
- Умение проектировать проверяемый код (возврат ошибок, логирование, метрики).
- Знание инструментов:
go test,race detector,pprof, observability-стек. - Способность рассуждать о правильности на уровне системы, а не только функции.
- Опыт с реальными кейсами: дедлайны, retry, идемпотентность, обработка частичных сбоев.
Типичные ошибки
- Ответ "если нет ошибки, значит правильно" - неверно, потому что ошибка может быть скрыта или бизнес-логика нарушена.
- Игнорирование ошибок через
_ = func()- грубая ошибка в Go. - Отсутствие тестов на негативные сценарии (ошибки БД, таймауты, дубли).
- Проверка только успешного пути, без проверки побочных эффектов.
- Уверенность, что логирование - это достаточная проверка, без метрик и алертов.
- Непонимание разницы между "код завершился" и "код завершился корректно" для фоновых задач.
> Похожие задачи по Go
Как написать запрос, который выберет названия всех книг с более чем тремя авторами
Какой индекс построить для запроса с условиями на несколько столбцов
Как программа определяет URL для выполнения запросов по списку
Как называются ресиверы в Go и когда использовать ресивер по значению или по указателю
> Похожие задачи по backend
Как написать запрос, который выберет названия всех книг с более чем тремя авторами
Какой индекс построить для запроса с условиями на несколько столбцов
Как программа определяет URL для выполнения запросов по списку
Как называются ресиверы в Go и когда использовать ресивер по значению или по указателю
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью