Загрузка…
Загрузка…
backend / middle / tech_deep
Формат
online
Стадия
tech_deep
Когда
within_quarter
Длительность
100 мин
01
Поведенческий
Расскажите про вашу текущую (последнюю) компанию: команду, откуда приходят задачи, как устроена работа.
Вводный блок в начале техсобеседования
02
Код
Лайвкодинг: на входе два отсортированных по возрастанию массива чисел — подозреваемые и невиновные. Необходимо из массива подозреваемых исключить всех невиновных. Сначала предложить идею решения, затем реализовать.
Кандидат решил через map[int]struct{} и один проход по suspects
03
Теория
Оцените асимптотическую сложность вашего решения по времени и по памяти.
Follow-up к задаче про подозреваемых; ответ: O(N) по времени, O(M) по памяти
04
Теория
Почему в качестве значения мапы выбрали пустую структуру, а не bool? В чём разница?
Заметки
Транскрипт видеозаписи реального технического собеседования (Go-разработчик) в компанию Плата — мексиканский финтех-стартап, основанный бывшими сотрудниками Тинькофф; общение на русском. Работа из России невозможна, после оффера возможен релокейт на Кипр, в Сербию или Казахстан. Структура интервью: вопросы про текущую компанию → лайвкодинг + глубокая теория по Go (мапы, слайсы, GC, шедулер) → задача на многопоточность → код-ревью (Go + SQL) → ситуационный кейс дежурного → экспресс по транзакциям, индексам, CAP и Kafka. Итог: кандидата позвали на следующий этап — System Design Interview. В середине транскрипта рекламная вставка автора канала (менторство по Go/фронтенду), к собеседованию не относится.
Стиль интервьюера
Дружелюбный, общение на «ты». Стиль — «докапываться до каждой вещи, которую используешь в коде»: по каждой конструкции из лайвкодинга идёт серия углубляющих вопросов. Даёт наводящие подсказки, предлагает порассуждать («ты бы как сделал?»), сам объясняет правильные ответы, когда кандидат не знает (overflow bucket, Stop the World, work stealing). Рисует схемы по ходу (GMP-модель), накидывает вводные в ситуационном кейсе. Оставляет время на вопросы кандидата и готов задержаться сверх полутора часов.
Follow-up: bool занимает 1 байт или 1 бит? Пустая структура — 0 байт
05
Теория
Зачем при создании мапы указали длину (capacity)? Что это даёт?
06
Теория
В каком случае мапа в Go создаёт новые бакеты? Как это происходит (эвакуация/ребалансировка), как работает хэш-функция и распределение по бакетам?
Обсуждали load factor 6.5, эвакуацию, рост мапы в 2 раза
07
Теория
Сколько элементов максимум лежит в одном бакете мапы в Go?
Ответ: 8 элементов
08
Теория
Если коллизия такая, что в полный бакет (8 элементов) нужно записать девятый элемент, а эвакуация ещё не наступила — что произойдёт? Что в бакете защищает от переполнения?
Ожидаемый ответ: overflow bucket
09
Теория
Можем ли мы как-то повлиять на хэш-функцию мапы, чтобы загрузить один бакет, не трогая остальные?
Ответ: нет, это внутренняя реализация Go
10
Теория
Что можно и что нельзя использовать в качестве ключей мапы в Go? Есть ли ограничения?
Разбирали: слайсы, массивы, мапы, функции, структуры с не-comparable полями
11
Теория
Почему массив можно использовать как ключ мапы, а слайс нельзя? В чём принципиальная разница между массивом и слайсом?
Follow-up к вопросу о ключах мапы
12
Теория
Зачем при make слайса передали длину 0 третьим аргументом capacity? Как работал бы make с другими аргументами (без нуля, с длиной = capacity)?
Разбирали zero values, len vs cap, поведение при разных вариантах make
13
Теория
Как именно работает append в Go? Что он делает под капотом?
Обсуждали рост capacity (x2 до порога, потом ~1.25), выделение новой памяти, перенос элементов
14
Теория
Какова максимальная асимптотическая сложность операции append?
Ответ: линейная (при реаллокации и переносе элементов)
15
Теория
Какой алгоритм используется сборщиком мусора в Go для нахождения мусора в программе? Как он работает?
Трёхцветная маркировка: белый/серый/чёрный
16
Теория
Останавливается ли весь процесс на время работы GC (Stop the World)? Как бы вы сделали: останавливали процесс или продолжали работу параллельно?
Интервьюер объяснил: два Stop the World (разметка рутов и доразметка), GC работает параллельно с программой
17
Теория
GC чистит хип. А как в Go чистится стек?
18
Теория
Что значит «переменная перекидывается на хип»? Как и когда это происходит?
Follow-up: рантайм перемещает переменную на хип, если она используется за пределами скоупа функции
19
Поведенческий
Приходилось ли профилировать Go-приложение? Расскажите, как это делали (pprof, какие эндпоинты).
Интервьюер отметил, что спросил из личного интереса
20
Код
Лайвкодинг по многопоточности: дан код — буферизированный канал на 1000 элементов, 100 горутин по 10 раз пишут в канал, далее range по каналу с накоплением суммы. Что напечатается в 12-й строчке?
Ответ: канал не закрывается, range зависнет — ничего не напечатается
21
Код
Поправьте код так, чтобы в 12-й строчке напечаталась правильная сумма (10000).
Решение: sync.WaitGroup, defer wg.Done(), отдельная горутина с wg.Wait() и close(ch)
22
Теория
Из чего состоит канал в Go? Какие поля есть в его структуре?
Кандидат вспомнил buf, sendx, recvx
23
Теория
Если бы в этой программе использовался небуферизированный канал — что-нибудь изменилось бы? Был бы дедлок?
Продебажили вместе: дедлока нет, так как чтение идёт параллельно
24
Теория
Что будет, если закрыть канал и попробовать в него записать? А прочитать из закрытого канала?
Ответ: запись — паника; чтение — zero values
25
Теория
Можно ли при чтении из канала (без range) проверить, что канал закрыт и пришло zero value, а не реальное значение?
Ответ: comma-ok идиома, как в мапе
26
Теория
Какой паттерн использует внутри себя шедулер Go? Расскажите, как он в целом работает (GMP-модель, M:N-планировка, статусы горутин, поведение при I/O и сисколах).
Обсуждали статусы running/runnable/waiting, вытеснение горутины после 10 мс (Go 1.14)
27
Теория
Куда шедулер перемещает горутину, которая заблокировалась на простой операции (запись в канал, sleep) — в локальную очередь или глобальную?
Ответ интервьюера: остаётся при своём P, выгоднее не перемещать; при долгих I/O создаётся новый тред ОС
28
Теория
Что произойдёт, если у одного P (очереди) закончились все горутины, а у других ещё есть?
Ответ: work stealing — забирает горутины с конца чужих локальных очередей, плюс глобальная очередь
29
Теория
Можем ли мы задать количество P (очередей) в Go? Как?
Ответ: runtime.GOMAXPROCS
30
Теория
Что плохого, если выставить GOMAXPROCS=8 при четырёх ядрах? Какие проблемы возможны?
Дорогое переключение потоков ОС между ядрами + перегон горутин между очередями вместо реальной работы
31
Теория
Какое значение GOMAXPROCS выставляется по дефолту?
Ответ: по количеству логических ядер процессора
32
Теория
Какая может быть опасность, если деплоишься в Kubernetes с лимитами на под и не выставляешь GOMAXPROCS руками?
Runtime видит ядра хостовой машины (например 16), а поду выделено 2 — дисбаланс
33
Код
Код-ревью: дан файл уровня репозитория (Go + SQL, метод save order status history). Проревьюируйте изменение, как делали бы это в реальной работе — замечания вслух или комментариями.
Кандидат нашёл: открытие соединения в каждом методе вместо connection pool/DI, fmt.Sprintf вместо плейсхолдеров $1..$4 (SQL-инъекции), time.Now() вместо created_at в базе, отсутствие контекста, отсутствие транзакций, клиентское партиционирование
34
Теория
Как обычно делается партиционирование в PostgreSQL? Нужно ли при insert указывать конкретную партицию? На основе какого поля вы бы здесь партиционировали?
Follow-up в рамках код-ревью: Postgres сам определяет партицию по полям строки; клиентское партиционирование — антипаттерн
35
Теория
В чём разница между %v и %w при проброске ошибки через fmt.Errorf?
%w оборачивает ошибку как объект (можно потом найти через errors.Is/As), %v — только текст
36
Кейс
Ты дежурный за сервис. Прилетает алерт в Slack: очень много логов с уровнем error. Расскажи, что будешь делать; интервьюер накидывает вводные (ошибки context deadline exceeded, метрики БД в порядке и т.д.) — докопайся до причины.
Два кейса: 1) долгие запросы к внешним сервисам из-за их бага; 2) не хватало индекса после резкого роста данных
37
Теория
Что ты хотел бы увидеть в EXPLAIN ANALYZE и как это поможет в диагностике медленного запроса?
Follow-up к ситуационному кейсу: index scan vs seq scan
38
Теория
Что такое транзакция и зачем она нужна?
39
Теория
Расшифруйте ACID — каким правилам должна удовлетворять транзакция?
40
Теория
В транзакции выполняется SELECT по условию, затем другие действия, затем точно такой же SELECT — и нужно получить те же данные. Какой уровень изоляции выбрать?
Ответ: repeatable read (snapshot)
41
Теория
На основе каких алгоритмов строятся индексы? Какие индексы вы использовали на практике?
Кандидат: b-tree почти всегда, hash для сравнений на равенство, gin для jsonb
42
Теория
Дан запрос с двумя условиями равенства (col1 и col2) — какой индекс вы бы использовали? Почему b-tree, а не hash? Можно ли составной hash-индекс?
43
Теория
Если в запросе поменять местами порядок условий (col2, потом col1) — составной индекс (col1, col2) всё ещё будет работать?
Ответ: да, Postgres умеет переставлять условия — порядок в WHERE не важен
44
Теория
Запрос с условиями по col1 и col3 при составном индексе — будет ли индекс использоваться? А если условия только по col2 и col3?
Ответ: частично используется (по col1); без первой колонки индекс не используется вообще
45
Теория
Слышал/читал ли про CAP-теорему? Расскажи. Сколько из трёх гарантий можно обеспечить одновременно?
46
Теория
Kafka: топик с четырьмя партициями, консюмер-группа с тремя консюмерами. Всё нормально будет, смогу так прочитать данные или нужно что-то поправить?
47
Теория
А если консюмеров в группе будет больше, чем партиций (шесть на четыре партиции) — что произойдёт?
Ответ: лишние консюмеры будут простаивать
48
Теория
Другая команда добавила свою консюмер-группу на тот же топик. Может ли случиться, что сообщение, прочитанное моей группой, они не увидят?
Ответ: нет, офсеты ведутся отдельно для каждой консюмер-группы
49
Теория
Какие гарантии доставки есть в Kafka и каким механизмом они обеспечиваются?
Обсуждали момент сдвига офсета: at-most-once (потеря) vs at-least-once (дубли), идемпотентность для борьбы с дублями
50
Теория
Гарантируется ли очередность получения сообщений при чтении из топика Kafka (сообщения 1-2-3-4 в разные партиции, несколько консюмеров в группе)?
Ответ: порядок гарантируется только внутри одной партиции, между партициями — нет