Загрузка…
Загрузка…
backend / middle / tech_deep
Формат
online
Стадия
tech_deep
Когда
within_quarter
Длительность
90 мин
01
Код
Напишите программу на Go, которая выполняет HTTP-запросы по списку URL и печатает результат (статус-код 200 или ошибку запроса).
Первая задача лайвкодинга. Интервьюер указал на баг: return внутри цикла завершает функцию на первой ссылке.
02
Теория
Почему нужно закрывать тело HTTP-ответа (resp.Body.Close()) в Go?
Теоретическая врезка по ходу первой задачи: ожидался ответ про утечку памяти/ресурсов.
03
Теория
В каком кейсе defer resp.Body.Close() не отработает корректно и приведёт к панике?
Follow-up к первой задаче: если запрос вернул ошибку, response будет nil — defer нужно ставить после проверки ошибки.
04
Код
Модифицируйте программу так, чтобы HTTP-запросы по списку URL выполнялись асинхронно с помощью горутин (горутины, канал результатов, sync.WaitGroup).
Заметки
Видео-запись технического собеседования в Озон (Go-бэкенд) из серии: HR-созвон, техскрининг, техническое и финальное интервью (остальные этапы — в других видео). Структура интервью: 3 итерации одной лайвкодинг-задачи на Go (HTTP-запросы → горутины → worker pool), код-ревью, архитектурная задача (order service + нестабильная аналитика, ожидался паттерн transactional outbox), SQL-секция (DDL, SELECT, индексы, EXPLAIN, шардирование). Интервью длилось чуть меньше полутора часов — это норма (≈15 мин на первую задачу, 15 на вторую, 10 на третью, ревью обычно занимает дольше всего). Фидбек — через рекрутёра после заполнения отчёта, точные сроки не гарантируются.
Подготовка
По фидбеку интервьюера: важно глубоко знать паттерн transactional outbox — если кандидат знает паттерн по имени, секция проходит быстро. Также полезно знать паттерн «стратегия», OWASP Top 10 (SQL-инъекции), worker pool и каналы в Go, виды индексов и EXPLAIN ANALYZE. Условия задач из видео можно взять из группы автора канала и порешать самостоятельно.
Стиль интервьюера
Интервьюер доброжелательный, активно направляет наводящими вопросами и подсказками (сам подсказал паттерн «стратегия» и outbox), разрешает проверять спорные моменты запуском кода, просит проговаривать рассуждения. Обратную связь сразу не даёт — заполняет отчёт, который смотрит команда; на вопросы кандидата в конце отвечает открыто.
Вторая итерация задачи. По ходу была ошибка компиляции, которую попросили исправить.
05
Теория
Почему вы выбрали небуферизированный канал? Когда используют буферизированные каналы?
Follow-up ко второй задаче. Кандидат: буферизированные — для rate limiter / семафора / worker pool, их поведение сложнее предсказать.
06
Код
Модифицируйте программу: URL приходят из внешнего источника (количество заранее неизвестно, может быть миллиард) — обработайте поток грамотно (канал URL, worker pool, контекст для отмены).
Третья итерация задачи. Обсуждали обработку закрытия канала и context.Done.
07
Теория
Что будет, если создавать отдельную горутину под каждый из миллиарда URL?
Наводящий follow-up к третьей задаче: упадём по памяти → нужен worker pool.
08
Код
Проведите код-ревью Go-программы (сервис, который каждую минуту опрашивает банки и собирает курсы валют): код рабочий, но содержит логические проблемы — найдите их и оставьте комментарии.
Найденное: лишние паники вместо логирования ошибок, необработанные ошибки, пароли/хосты в константах кода (нужны env/секреты), токен в явном виде, дублирование структуры, двойная обработка ошибки (checkError), открытие коннекшна к БД на каждый запрос вместо пула.
09
Теория
Какой архитектурный паттерн подойдёт, если завтра придётся интегрироваться с новыми банками по другим протоколам (gRPC, FTP), а не выносить всё в одну структуру?
Кандидат предложил фабрику и билдер; интервьюер подсказал паттерн «стратегия» — один интерфейс, своя реализация на протокол.
10
Теория
Чем грозит формирование SQL-запроса прямой подстановкой значений (без параметров $1)? Знаете ли что-нибудь про OWASP Top 10?
Кандидат не слышал про OWASP Top 10; интервьюер пояснил — такая запись грозит SQL-инъекциями, нужны параметризованные запросы.
11
Теория
Правильно ли открывать новое подключение к базе данных при каждом вызове update currency? Как это обычно делают?
Вывод: коннекшн открывают один раз / используют пул коннекшенов, паника уместна только при первом открытии.
12
System design
Архитектурная задача: пользователь создаёт заказ, order service отправляет данные в сервис аналитики, который работает нестабильно (500-ит, таймаутит), и пользователь долго висит, данные теряются. Как исправить ситуацию?
Кандидат предложил асинхронность через очередь (Kafka/RabbitMQ) — поинт засчитан валидным.
13
System design
Сервис аналитики не готов внедрять Kafka — у них остаётся та же синхронная HTTP-ручка. Как организовать надёжную асинхронную доставку аналитики на своей стороне, не теряя сообщения и сразу отпуская пользователя?
Интервьюер хотел услышать паттерн transactional outbox (запись в таблицу БД → воркер вычитывает → Kafka → отправка в аналитику). Кандидат описал его частично, но не назвал и не показал глубокого понимания — это отметили в фидбеке.
14
System design
Из-за этого решения на сервис аналитики идёт высокий RPS. Как придумать (экспоненциальное) решение, которое будет повышать или понижать нагрузку в зависимости от текущего состояния сервиса аналитики?
Кандидат предложил динамически менять количество воркеров в зависимости от нагрузки.
15
Код
SQL-задача: спроектируйте таблицы (DDL в стандартном синтаксисе) для сущностей «пользователь» (имя, дата регистрации), «чат» и «сообщение» (текст, автор, дата создания).
Замечания интервьюера: задвоенный тип у id (нужен serial PK), забытое поле message в таблице, foreign key можно не прописывать.
16
Код
Напишите SELECT по этим таблицам: получить все чаты пользователя (Вася) через JOIN.
17
Теория
Если в этом запросе вместо JOIN написать LEFT JOIN — что изменится?
Правильный ответ для данного запроса — ничего не поменяется; кандидат сначала ответил неверно, потом поправился.
18
Теория
Что такое индексы в базах данных?
19
Теория
Какие виды индексов бывают и когда какой лучше использовать (B-tree, hash, bitmap)?
Ответ кандидата: hash — точные совпадения, B-tree — сортировка/поиск по диапазону, bitmap — поля с низкой кардинальностью (пол, статус).
20
Теория
Какие индексы уже будут автоматически созданы для этих четырёх таблиц и по каким полям?
Ожидаемый ответ: на primary key автоматически создаётся B-tree индекс.
21
Теория
Данных стало больше, запрос стал медленно работать. Как найти причину медленного запроса?
Ответ кандидата: EXPLAIN ANALYZE (+ VERBOSE), метрики cost/rows, поиск Seq Scan, дорогих сортировок и nested loops.
22
Теория
Все нужные индексы уже есть, EXPLAIN ничего не предлагает, но запрос всё равно медленный. Что ещё можно сделать?
Кандидат предложил партиционирование таблицы (например, по кварталам) / шардирование.
23
Теория
Сможем ли мы безболезненно шардировать таблицу messages в текущем виде, учитывая потенциальный рост до миллиардов сообщений? Какой ключ шардирования выбрать?
Ожидаемый ответ: serial id не даёт глобальной уникальности — нужен UUID в качестве ключа.
24
Теория
Какие ещё инструменты, кроме шардирования, помогают оптимизировать запросы / масштабировать базу данных?
Ответ кандидата: репликация (master-slave, чтение с реплик), но для чата с частой записью это менее эффективно; разнести на несколько хостов.