Загрузка…
Загрузка…
backend / middle / tech_deep
Формат
online
Стадия
tech_deep
Когда
within_quarter
Длительность
60 мин
01
Код
Дан код на Go: структура создаётся как указатель и передаётся в функцию, принимающую указатель, внутри которой указателю присваивается новый объект. Что выведет программа и почему?
Первая задача в онлайн-песочнице: разбор вывода программы (Боб/Алиса). Кандидат сначала ошибся, потом объяснил, что при копировании указателя внутри функции новый объект присваивается локальной копии.
02
Код
Модифицируй код так, чтобы изменение применилось к исходному объекту и во второй раз вывелось новое значение.
Follow-up к задаче про указатели.
03
Теория
Какие ещё есть варианты это сделать (помимо разыменования указателя — например, передать указатель на указатель)?
Follow-up к задаче про указатели.
04
Код
Реализуй для HTTP-ручки подсчёт отношения количества ошибок к общему количеству запросов и вывод этого отношения в консоль раз в секунду.
Заметки
Секция «Платформа Go» (в конце кандидат задаёт вопросы про работу в Авито). Формат: 3 задачи лайвкодинга в онлайн-песочнице (указатели и вывод программы; счётчик ошибок ручки с периодическим выводом; обёртка с тайм-аутом через context/select) + теоретический блок по Go (горутины, планировщик GMP, runtime, каналы, примитивы синхронизации, интерфейсы, slice/map, GC, тестирование, профилирование). В конце выделено время на вопросы кандидата.
Стиль интервьюера
Общение на «ты», доброжелательный тон. Интервьюер активно задаёт уточняющие follow-up'ы по ходу решения задач («почему atomic, а не Mutex?», «что происходит на этой строке?»), подсказывает при ошибках (забытый таймаут контекста), пропускает вопрос, если кандидат честно говорит, что не помнит.
Вторая задача лайвкодинга. Кандидат использовал atomic-счётчики, отдельную структуру с методами и отдельную горутину с тикером.
05
Теория
Для чего ты здесь используешь atomic?
Теоретическая врезка по ходу задачи про счётчик ошибок (параллельные запросы к ручке, защита от гонки данных).
06
Теория
Как организовать периодический вывод раз в секунду — нужно ли это делать внутри хендлера, или можно запустить отдельную горутину из main?
Follow-up по ходу задачи про счётчик ошибок.
07
Теория
Для чего ты хотел передать контекст в горутину?
Follow-up: кандидат ответил — чтобы горутина не работала бесконечно и не было утечки.
08
Теория
Расскажи, что происходит на строке с ожиданием тикера (как работает чтение из канала time.Ticker в цикле for)?
Теоретическая врезка по коду задачи про счётчик ошибок («что происходит на пятидесятой строке»).
09
Теория
Почему ты использовал atomic, а не какой-то другой примитив синхронизации (например, Mutex)?
Обсуждали, что atomic дешевле и что Mutex внутри сам построен на atomic.
10
Теория
Что такое горутина и чем она отличается от потока операционной системы?
Начало теоретического блока: легковесность, динамический стек, переключение контекста.
11
Теория
За счёт чего достигается легковесность горутин?
Follow-up: размер стека, отсутствие данных уровня ОС (регистры и т.д.).
12
Теория
Расскажи подробнее про планировщик Go — как он работает (модель GMP)?
Кандидат рассказал про G/M/P, локальные и глобальную очереди, netpoll, work stealing.
13
Теория
Когда у процессора (P) заканчивается локальная очередь горутин — куда он идёт: сначала в глобальную очередь, потом ворует из других локальных очередей?
Уточняющий follow-up к вопросу про планировщик.
14
Теория
Чем занимается рантайм Go? Что он вообще делает?
Кандидат назвал планировщик и garbage collector.
15
Теория
Какие функции есть у рантайма Go?
Follow-up; кандидат не вспомнил, интервьюер пропустил вопрос.
16
Теория
За счёт чего Go позволяет работать с большим количеством сетевых соединений?
Обсуждали горутину на запрос и очередь netpoll для ожидания сетевых ответов.
17
Теория
Что такое каналы в Go и для чего они нужны?
Буферизированные/небуферизированные, закрытие канала, паника при записи в закрытый канал.
18
Теория
Что будет, если записать в nil-канал?
Follow-up к вопросу про каналы.
19
Теория
Что будет, если прочитать из nil-канала?
Follow-up к вопросу про каналы.
20
Теория
Как выполняется передача значений из одной горутины в другую через канал — как канал работает внутри?
Обсуждали копирование из стека в стек для небуферизированных каналов и оптимизацию при пустом буфере.
21
Теория
Как реализован буфер канала внутри?
Follow-up; ответ — кольцевая очередь.
22
Поведенческий
Приходилось ли тебе на практике использовать эти особенности записи/чтения каналов?
Вопрос про практический опыт по ходу теории о каналах.
23
Теория
Какие ещё примитивы синхронизации в Go знаешь, кроме atomic и Mutex?
Кандидат назвал RWMutex (параллельное чтение), WaitGroup, каналы как примитив синхронизации.
24
Теория
Что такое интерфейс в Go?
Обсуждали контракты, неявную имплементацию (утиная типизация).
25
Теория
Из чего состоит интерфейс внутри (внутреннее устройство)?
Follow-up: поле с информацией о типе и его методах + само значение типа.
26
Код
Реализуй обёртку над unpredictable-функцией с тайм-аутом: запусти её в отдельной горутине, ожидай результат через канал и select с контекстом; при превышении тайм-аута верни ошибку.
Третья задача лайвкодинга. Кандидат использовал буферизированный канал (буфер 1), чтобы горутина не зависала после возврата по тайм-ауту.
27
Код
Добавь измерение того, сколько времени выполнялась функция.
Часть условия третьей задачи, добавленная по ходу.
28
Теория
В select обрабатываются два кейса — отмена контекста и результат функции. Завершится ли в текущем коде контекст когда-нибудь (передан ли тайм-аут)?
Follow-up: кандидат забыл создать context.WithTimeout, после подсказки исправил; обсудили cancel/defer.
29
Код
Доработай unpredictable-функцию, чтобы она возвращала ещё и ошибку, и обработай её в обёртке.
Follow-up к третьей задаче.
30
Теория
Мы закрываем канал в конце — а нужно ли вообще его закрывать в этом случае?
Follow-up к третьей задаче; обсуждали, что закрытие здесь значения не имеет.
31
Теория
Чем slice отличается от map в Go (использование памяти, устройство)?
Динамический массив vs хэш-таблица, доступ за O(1) амортизированно, какие типы могут быть ключом (comparable).
32
Теория
Чем длина слайса (len) отличается от его ёмкости (cap)?
Follow-up к вопросу про slice/map.
33
Теория
Что происходит, когда нужно добавить элементы в слайс, а capacity уже исчерпана?
Обсуждали удвоение до 1024 элементов и рост по формуле дальше.
34
Теория
Что происходит со старыми данными при расширении слайса?
Follow-up: данные копируются из старого массива в новый.
35
Теория
А как рост и расширение работают в map?
Бакеты по 8 элементов, инкрементальная эвакуация данных при записи.
36
Теория
Как происходит сборка мусора в Go?
Кандидат рассказал про mark&sweep, трёхцветную маркировку, write barrier и stop-the-world только в начале.
37
Поведенческий
Приходилось ли тебе писать тесты? Какие виды тестов знаешь?
Юнит, функциональные, интеграционные, end-to-end.
38
Теория
Знаешь какие-нибудь полезные аргументы команды go test?
Кандидат не вспомнил конкретных флагов, запускал просто go test ./...
39
Теория
Что такое моки и для чего они нужны?
40
Поведенческий
Сталкивался ли ты с профилированием программ?
Кандидат плотно не занимался, но pprof в проекте есть.
41
Теория
Для чего вообще нужно профилирование?
Follow-up к вопросу про профилирование.
42
Теория
Какие ещё параметры можно посмотреть при профилировании, кроме памяти?
Кандидат не вспомнил, интервьюер пропустил вопрос.