сеньорчикОткрыть в Telegram
← все вопросывопросы для собеседований · Горутины и каналы

Вопросы по горутинам и каналам Go на собеседовании

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

66 вопросов в банке·10 подтем·ниже разбор 9

Из чего состоит тема

Так тема разложена в тренажёре: движок ведёт прогресс по каждой подтеме отдельно и возвращает те, где вы ошибаетесь.

Разборы подтем

Конспект по каждой: что это, как отвечать вслух, на чём валятся, плюс вопросы для самопроверки.

Примеры вопросов с разбором

  1. #go_chan_pitfalls1 / 9
    Горутина выполняет ch <- v, но канал к этому моменту уже закрыт. Что будет?
    A)Значение молча отбрасывается
    B)v кладётся в буфер и прочитается после переоткрытия канала
    C)Паника рантайма: send on closed channel
    D)Отправка блокируется до повторного открытия канала
    показать ответ и разбор
    +C)Паника рантайма: send on closed channel

    // разбор: Отправка в закрытый канал — паника рантайма «send on closed channel». Каналы не переоткрываются: close необратим. Отсюда классическая гонка — писатель шлёт после того, как канал закрыл кто-то другой. Лечится координацией: закрывает один владелец, а писатели узнают об остановке через отдельный сигнал (context/done) и прекращают отправку до close.

  2. #go_channels2 / 9
    Небуферизованный канал. Что делает отправка ch <- v, если получателя ещё нет?
    A)Блокирует горутину-отправителя, пока другая горутина не примет значение
    B)Кладёт значение во внутренний буфер канала и немедленно продолжает работу дальше
    C)Возвращает ошибку об отсутствии получателя
    D)Молча отбрасывает значение, раз его некому принять
    показать ответ и разбор
    +A)Блокирует горутину-отправителя, пока другая горутина не примет значение

    // разбор: У небуферизованного канала (cap 0) отправка и приём — рандеву: отправитель блокируется, пока другая горутина не будет готова принять (и симметрично наоборот). Буфера нет, поэтому «положить и уйти» невозможно. Если принять окажется некому и других горутин нет — рантайм фиксирует дедлок с фатальной ошибкой.

  3. #go_goroutine_leaks3 / 9
    Что называют утечкой горутины (goroutine leak)?
    A)Горутину, которая вечно заблокирована и потому не завершается
    B)Горутину, съедающую слишком много CPU в бесконечном цикле
    C)Утечку памяти из-за того, что горутина не вызвала runtime.GC()
    D)Ситуацию, когда горутин создано больше, чем значение GOMAXPROCS
    показать ответ и разбор
    +A)Горутину, которая вечно заблокирована и потому не завершается

    // разбор: Утечка — горутина, которая никогда не завершится, потому что вечно ждёт события, которое не наступит: приём из канала без отправителя, отправку в канал без читателя, ожидание на sync-примитиве. Она держит свой стек и захваченные переменные, и память не освобождается. GC заблокированную горутину не собирает — формально она «жива». Копятся тихо, всплывают под нагрузкой.

  4. #go_goroutines4 / 9
    Что такое горутина в Go?
    A)Системный поток ОС, создаваемый напрямую через syscall на каждый вызов go
    B)Процесс операционной системы с собственным адресным пространством
    C)Синтаксический сахар: код откладывается и выполняется в конце функции
    D)Лёгкий поток, которым управляет рантайм Go, а не ОС
    показать ответ и разбор
    +D)Лёгкий поток, которым управляет рантайм Go, а не ОС

    // разбор: Горутина — функция, запущенная через go. Рантайм мультиплексирует тысячи горутин на небольшое число потоков ОС (модель M:N), стек стартует с ~2 КБ и растёт по мере надобности. Поэтому горутины дёшевы — их держат сотнями тысяч. Поток ОС, наоборот, тяжёлый: мегабайты стека, дорогой контекст-свитч через ядро.

  5. #go_select5 / 9
    Зачем в select нужна ветка default?
    A)Задаёт case, который срабатывает после того, как отработают остальные
    B)Ловит панику из других case, как это делает recover
    C)Задаёт порядок проверки: сначала default, потом готовые каналы
    D)Делает операцию неблокирующей: нет готовых case — сразу default
    показать ответ и разбор
    +D)Делает операцию неблокирующей: нет готовых case — сразу default

    // разбор: Без default select блокируется, пока хотя бы один case не станет готов. Ветка default выполняется немедленно, если в момент проверки не готов ни один канал, — так делают неблокирующие приём и отправку, опросы. Если готовых case несколько, select выбирает один псевдослучайно; default вступает в игру только когда готовых нет вовсе.

  6. #go_context6 / 9
    Зачем в Go нужен context.Context?
    A)Пронести отмену, дедлайн и request-scoped данные по цепочке вызовов
    B)Хранить глобальное состояние приложения вместо переменных пакета
    C)Заменить каналы для передачи больших объёмов данных между горутинами напрямую
    D)Автоматически ограничивать память, которую может занять одна горутина
    показать ответ и разбор
    +A)Пронести отмену, дедлайн и request-scoped данные по цепочке вызовов

    // разбор: context несёт сигнал отмены и дедлайн вниз по дереву вызовов и горутин: отменили корневой — узнали все, кто слушает ctx.Done(). Плюс request-scoped значения (trace-id, дедлайн запроса). Первым аргументом ctx принимают HTTP-хендлеры, RPC, запросы к БД. Это не хранилище состояния и не транспорт данных — про управление жизненным циклом.

  7. #go_data_race7 / 9
    Что такое гонка данных (data race) в Go?
    A)Ситуация, когда две горутины соревнуются, кто первой захватит мьютекс
    B)Незащищённый конкурентный доступ к одной памяти, где хотя бы один — запись
    C)Недетерминированный порядок запуска горутин при каждом старте программы
    D)Программа ведёт себя по-разному в зависимости от того, какая горутина закончит первой
    показать ответ и разбор
    +B)Незащищённый конкурентный доступ к одной памяти, где хотя бы один — запись

    // разбор: Гонка данных — конкурентный доступ двух и более горутин к одной ячейке памяти без синхронизации, где хотя бы одна операция — запись. Результат не определён: от «повезло» до порчи данных и падений. Это уже, чем race condition (та про порядок событий вообще). Лечится синхронизацией — мьютекс, atomic, канал. Детектор -race ловит их на рантайме.

  8. #go_mutex_atomic8 / 9
    Зачем нужен sync.Mutex?
    A)Ускоряет доступ к общей памяти, кэшируя её значение между горутинами
    B)Взаимное исключение: секцию Lock–Unlock держит одна горутина за раз
    C)Помечает переменную потокобезопасной, пока с ней работает горутина
    D)Создаёт отдельную копию данных каждой горутине, чтобы они не пересекались
    показать ответ и разбор
    +B)Взаимное исключение: секцию Lock–Unlock держит одна горутина за раз

    // разбор: Mutex сериализует доступ к общим данным: Lock() входит в критическую секцию, Unlock() выпускает; пока один держит замок, другие горутины на Lock блокируются. Так защищают инвариант, который ломает конкурентная запись (например counter++). Это не кэш и не «магическая» безопасность переменной — защищает именно дисциплина: все идут через один и тот же мьютекс.

  9. #go_sync_patterns9 / 9
    Структура со встроенным sync.Mutex передана в метод с получателем-значением func (s S). В чём риск?
    A)Копируется и мьютекс — Lock идёт по разным копиям, защита не работает
    B)Встроенный мьютекс требует, чтобы структуру передавали через указатель
    C)Компилятор отклонит код: копировать sync.Mutex запрещено
    D)Ничего: Go передаёт встроенный мьютекс по ссылке, даже если получатель — значение
    показать ответ и разбор
    +A)Копируется и мьютекс — Lock идёт по разным копиям, защита не работает

    // разбор: Получатель-значение копирует всю структуру, включая Mutex. Копия мьютекса — независимый замок с обнулённым состоянием, поэтому горутины блокируются на разных копиях и синхронизации нет (а копирование залоченного и вовсе даёт битое состояние). go vet это ловит: «passes lock by value». Правило: методы со встроенным мьютексом — на получателе-указателе. Спот-чек подтвердил варнинг.

это 9 из 66

Ещё 57 вопросов по теме — в тренажёре, с движком повторения

Прочитать разбор и ответить самому — разные навыки. В Сеньорчике вопросы идут сессиями, а движок возвращает подтемы, где вы ошибаетесь, пока они не начнут отскакивать. Бесплатно, лимит по энергии.

Частые вопросы