> Как устроена разработка сервисов: существующие или с нуля (Go)

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

Компании: BetBoom

Стек: Go

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

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

Разработка сервисов делится на два сценария: greenfield (с нуля) и brownfield (существующие). Для greenfield ключевое - выбор архитектуры, протоколов, структуры репозитория и CI/CD. Для brownfield - анализ текущего кода, обратная совместимость, миграции и постепенное улучшение. В обоих случаях важно соблюдать идиоматичность Go, явную обработку ошибок, контексты, graceful shutdown и тестируемость. Сеньор должен уметь оценивать trade-off между скоростью разработки и долгосрочной поддерживаемостью.

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

Разработка сервисов в Go на практике сводится к нескольким ключевым аспектам, независимо от того, создаётся сервис с нуля или развивается существующий.

Greenfield (с нуля):

  • Определение границ сервиса: что он делает, какие данные хранит, какие API отдаёт.
  • Выбор транспортного протокола: REST (net/http), gRPC, или комбинация. Для внутренних сервисов часто предпочитают gRPC, для внешних - REST.
  • Структура проекта: стандартная раскладка (cmd/, internal/, pkg/) или более плоская, если сервис небольшой.
  • Конфигурация: env-переменные, флаги, файлы конфигурации. В Go часто используют envconfig или viper.
  • Логирование, метрики, трейсинг: сразу закладываются интерфейсы, чтобы не переписывать потом.
  • Graceful shutdown: обработка сигналов, завершение воркеров, закрытие соединений.
  • Тестирование: unit-тесты на бизнес-логику, интеграционные тесты с тестовыми контейнерами.

Brownfield (существующие):

  • Первичный анализ: чтение кода, поиск узких мест, понимание текущих паттернов.
  • Обратная совместимость: изменение API без ломки клиентов, версионирование (например, /v1/).
  • Миграции: базы данных, конфигурации, деплой. Важно уметь раскатывать изменения без даунтайма.
  • Рефакторинг: постепенное улучшение, не ломая функциональность. Например, вынос бизнес-логики из хендлеров, введение интерфейсов для зависимостей.
  • Технический долг: приоритизация, что чинить в первую очередь, что оставить.

Общие принципы для Go:

  • Ошибки - это значения: явная проверка, оборачивание через fmt.Errorf с %w, errors.Is/As.
  • Контексты: передача ctx во все I/O операции, таймауты, отмена.
  • Горутины: контроль жизненного цикла, errgroup, каналы, отсутствие утечек.
  • Интерфейсы: определять на стороне потребителя, а не производителя.
  • Middleware: логирование, recover, rate limiting, аутентификация.

На практике

На практике сеньор в Go чаще сталкивается с brownfield, потому что большинство сервисов уже написаны. Но умение строить с нуля тоже важно - например, при выделении нового сервиса из монолита.

Для greenfield:

  • Начинать с минимального каркаса: main.go, конфиг, healthcheck, метрики. Дальше добавлять бизнес-логику.
  • Использовать стандартную библиотеку net/http, если не нужен gRPC. Она достаточна для большинства задач.
  • Не тащить тяжёлые фреймворки. Достаточно chi или стандартного mux.
  • Сразу настраивать линтеры (golangci-lint), gofmt, goimports.

Для brownfield:

  • Сначала найти все места, где сервис может упасть: паника, утечка горутин, необработанные ошибки.
  • Проверить, как обрабатываются сигналы завершения.
  • Посмотреть, как устроены миграции БД: golang-migrate, goose, или самописные.
  • Оценить тестовое покрытие. Если его нет - начать с ключевых сценариев.

Инструменты:

  • docker-compose для локальной разработки.
  • Makefile для стандартных команд (build, test, lint, run).
  • GitHub Actions или GitLab CI для пайплайнов.

Пример кода

Пример graceful shutdown и обработки контекста в Go:

GO
func main() {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
srv := &http.Server{
Addr: ":8080",
Handler: routes(),
}
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %v", err)
}
}()
<-ctx.Done()
stop()
log.Println("shutting down...")
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := srv.Shutdown(shutdownCtx); err != nil {
log.Fatalf("server forced to shutdown: %v", err)
}
log.Println("server exited")
}

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

  • Начни с разделения сценариев: greenfield и brownfield. Это покажет структурированность мышления.
  • Для greenfield перечисли ключевые решения: протокол, структура, конфигурация, observability.
  • Для brownfield акцентируй внимание на обратной совместимости, миграциях и рефакторинге без ломки.
  • Упомяни специфику Go: контексты, ошибки, горутины, graceful shutdown.
  • Приведи пример из практики: как ты выделял сервис из монолита или как улучшал существующий.
  • Не углубляйся в детали реализации, если не спрашивают. Держи ответ на уровне архитектуры и trade-off.
  • Если спрашивают про конкретный инструмент - отвечай кратко, но покажи, что знаешь альтернативы.

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

  • Умение оценивать масштаб задачи: что важно на старте, что можно отложить.
  • Понимание жизненного цикла сервиса: от создания до поддержки.
  • Знание идиоматичного Go: не просто "умею писать на Go", а понимание паттернов.
  • Способность принимать решения: почему gRPC, а не REST, почему chi, а не net/http.
  • Навыки работы с существующим кодом: чтение, анализ, рефакторинг.
  • Умение говорить про trade-off: скорость vs надёжность, простота vs гибкость.

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

  • Предлагать переписать существующий сервис с нуля без веских причин. Это красный флаг.
  • Игнорировать обратную совместимость при изменении API.
  • Не упоминать тестирование и observability - это сразу снижает оценку.
  • Использовать тяжёлые фреймворки без необходимости.
  • Не говорить про graceful shutdown и обработку сигналов.
  • Забывать про контексты и таймауты в I/O операциях.
  • Путать greenfield и brownfield подходы: например, предлагать полный рефакторинг для маленького сервиса, который просто нужно доработать.
  • Не упоминать миграции БД и их влияние на деплой.

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

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