> Как понять, что код отработал правильно (Go)

Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: Ozon

Стек: Go

> Пример ответа

Короткий ответ

Понять, что код отработал правильно, можно через комбинацию проверок: явные возвращаемые ошибки, логирование ключевых этапов, метрики и observability, а также тесты (unit, integration, e2e). В Go особенно важно не игнорировать error-значения и проверять их сразу после вызова. Для долгоиграющих процессов нужны health checks и алерты. Правильность - это не только отсутствие паники, но и соответствие ожидаемому поведению системы в целом.

Подробное объяснение

Правильность выполнения кода в Go складывается из нескольких уровней:

  1. Контракт функции - функция возвращает ожидаемый результат или ошибку. В Go это явно: if err != nil после каждого вызова, который может завершиться неудачей. Если функция не возвращает ошибку, но может упасть - это нарушение контракта.

  2. Состояние системы - после выполнения кода внешние зависимости (БД, кэш, очередь) должны находиться в ожидаемом состоянии. Проверяется через интеграционные тесты и ручную проверку в staging.

  3. Побочные эффекты - запись в лог, отправка метрик, изменение конфигурации. Они должны происходить ровно столько раз, сколько ожидается (идемпотентность, отсутствие дублей).

  4. Производительность и ресурсы - код не должен утекать по памяти, горутинам, соединениям. Проверяется через pprof, go test -race, нагрузочное тестирование.

  5. Наблюдаемость - в 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 и запись результата в хранилище.

Важно различать "код выполнился без ошибок" и "код сделал то, что нужно". Второе проверяется только через бизнес-логику и тесты на неё.

Пример кода

GO
func 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. Логирование успеха для observability
logger.Info("order processed", "order_id", orderID)
return nil
}

Правильность здесь определяется: ошибка возвращается на каждом шаге, успех логируется, состояние БД меняется только после всех проверок.

Как отвечать на собеседовании

Начните с базового: "правильность - это соответствие ожидаемому поведению, а не просто отсутствие ошибок". Затем перечислите уровни проверки: ошибки, тесты, метрики, логи. Подчеркните специфику Go: явная обработка ошибок, defer для cleanup, context для отмены. Приведите пример из практики, где код формально работал, но делал не то (например, гонка данных или потерянный error). Завершите мыслью о том, что в production правильность - это непрерывный процесс наблюдения, а не разовая проверка.

Что проверяет интервьюер

Интервьюер оценивает:

  • Понимание, что ошибки в Go - это значения, и их нельзя игнорировать.
  • Умение проектировать проверяемый код (возврат ошибок, логирование, метрики).
  • Знание инструментов: go test, race detector, pprof, observability-стек.
  • Способность рассуждать о правильности на уровне системы, а не только функции.
  • Опыт с реальными кейсами: дедлайны, retry, идемпотентность, обработка частичных сбоев.

Типичные ошибки

  • Ответ "если нет ошибки, значит правильно" - неверно, потому что ошибка может быть скрыта или бизнес-логика нарушена.
  • Игнорирование ошибок через _ = func() - грубая ошибка в Go.
  • Отсутствие тестов на негативные сценарии (ошибки БД, таймауты, дубли).
  • Проверка только успешного пути, без проверки побочных эффектов.
  • Уверенность, что логирование - это достаточная проверка, без метрик и алертов.
  • Непонимание разницы между "код завершился" и "код завершился корректно" для фоновых задач.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью