β
Войти Регистрация

Теоретические задачи Go: полный разбор для собеседования

Лид: теория Go до кода на доске

Готовитесь к собеседованию на Go? Ниже — 21 теоретический вопрос, который часто звучит до live-coding. Не список определений, а как устроены горутины, каналы, планировщик и сборщик мусора — то, что отличает уверенный ответ от «слышал, но не копал».

Вопросы сгруппированы по уровням. Старт — с базового. Middle+ — средний и продвинутый. Это шпаргалка редакции, не секретный банк конкретной компании. Воронка с Go разобрана в гайде Авито; соседние раунды — теория алгоритмов и System Design.

GMP помните, а речь срывается — проговорите схему на моке с напарником. Дыру в каналах ловит квиз. Оффер не выдаём.

Базовый уровень

1. Чем отличается var от :=?

Оба способа создают переменные, но работают в разных контекстах.

Сравнение var и короткого объявления
Критерий var :=
Где можно Внутри и вне функций Только внутри функций
Тип Явный или вывод Всегда выводится
Нулевое значение Да Нет, нужно присвоить
Без значения var x int Нельзя
var x int          // x = 0
var y = "hello"    // тип string выведен

func main() {
    name := "Gopher"  // только внутри функции
    age := 30
}

2. Что такое горутина и чем она отличается от потока ОС?

Горутина — легковесный поток выполнения, которым управляет рантайм Go, а не операционная система. Это архитектурное решение языка, не «поток поменьше».

Горутина и поток ОС
Характеристика Горутина Поток ОС
Начальный стек ~2 КБ, растёт ≥1 МБ, обычно фиксирован
Создание Дешёвое Дорогое, syscall
Контекст User space Через ядро
Кто планирует Рантайм Go Планировщик ОС
Сколько живут Десятки тысяч Сотни–тысячи

Модель M:N: множество горутин (G) крутятся на небольшом числе системных потоков (M) через логические процессоры (P).

3. Как работают каналы?

Каналы — типизированные конвейеры для передачи данных между горутинами. Через них обычно избегают гонок без явных блокировок.

ch := make(chan int)  // небуферизированный
ch <- 5               // отправка
value := <-ch         // получение
close(ch)             // закрытие

Пока GMP не уехало с языка

Разницу горутины и потока ОС дешевле сказать вслух, чем зубрить таблицу. Оффер не обещаем.

Найти напарника Экспресс-квиз

Средний уровень

4. Как планировщик вытесняет горутину и что такое work-stealing?

Планировщик использует work-stealing: пустой P забирает горутины у соседа. С Go 1.14+ планировщик вытесняющий: долгая горутина может быть прервана, даже если сама не делает вызов в рантайм.

go func() {
    // код горутины
}()

На раунде ждут не определение горутины, а вытеснение с 1.14 и work-stealing: пустой P забирает очередь соседа.

5. Чем буферизированные каналы отличаются от небуферизированных?

Буфер канала
Тип Создание Отправка Получение
Без буфера make(chan T) Ждёт получателя Ждёт данные
С буфером make(chan T, n) Ждёт, только если буфер полон Ждёт, только если буфер пуст

Как это выглядит

  • Без буфера отправитель и получатель встречаются синхронно: оба ждут друг друга.
  • С буфером ёмкости 3 значения сначала складываются в очередь. Отправитель не блокируется, пока есть место. Получатель не блокируется, пока очередь не пуста.

6. Что произойдёт при записи в nil-канал?

Операции с nil-каналом
Операция Результат
ch <- value Вечная блокировка
<-ch Вечная блокировка
close(ch) panic: close of nil channel

Nil-канал компилируется. Это ловушка рантайма. Для неблокирующих операций берут select с default.

7. Что такое интерфейс в Go и чем он отличается от Java?

Интерфейс — набор сигнатур методов. Тип удовлетворяет ему неявно, если реализует все методы. Ключевого слова implements нет.

type Writer interface {
    Write([]byte) (int, error)
}

type MyWriter struct{}

func (m MyWriter) Write(data []byte) (int, error) {
    return len(data), nil
}
// MyWriter удовлетворяет Writer без implements
Интерфейсы Go и Java
Аспект Go Java
Реализация Неявная implements
Чужой тип Можно закрыть методами Только свои классы
Содержимое Только методы Методы, константы, default
Пустой any / interface{} Object

8. Для чего нужна функция defer?

defer откладывает вызов до выхода из окружающей функции. Порядок — LIFO: последний отложенный вызов выполняется первым. Аргументы считаются сразу, в точке defer.

func example() {
    defer fmt.Println("1")  // третьим
    defer fmt.Println("2")  // вторым
    fmt.Println("3")        // первым
}
// Вывод: 3 2 1

9. Как эффективно соединить много строк?

Берите strings.Builder: меньше аллокаций. Конкатенация через + в цикле каждый раз создаёт новую строку — строки в Go неизменяемы.

var builder strings.Builder
for i := 0; i < 1000; i++ {
    builder.WriteString("data")
}
result := builder.String()

Канал на бумажке и канал вслух

Nil-канал и буфер лучше объяснить напарнику, чем пересказать таблицу. Оффер не обещаем.

Найти напарника Экспресс-квиз

Продвинутый уровень

10. Как устроены каналы внутри?

В рантайме канал — структура hchan. На раунде ждут не все поля наизусть, а очередь ждущих и буфер под мьютексом.

Поля hchan
Поле Смысл
qcount / dataqsizСколько элементов в буфере и какой у него размер
bufУказатель на кольцевой буфер
sendx / recvxИндексы отправки и получения
recvq / sendqОчереди ждущих получателей и отправителей
lockМьютекс канала

11. Как устроен планировщик в Go?

Планировщик — модель M:N. G — горутина. M — системный поток. P — логический процессор с локальной очередью. Work-stealing: пустой P ворует работу. С 1.14 — вытеснение.

GMP коротко

  1. Много G ждут в очередях.
  2. Каждый P держит свою локальную очередь.
  3. M исполняет G, привязанный к P.
  4. Пустой P забирает половину очереди у соседа.

12. Какая модель многозадачности в Go?

CSP: communicating sequential processes. Формула с раунда: не общайтесь через общую память — общайтесь сообщениями. Горутины независимы, каналы синхронизируют. Разделяемая память допустима, но не основной паттерн.

13. Как устроен сборщик мусора?

GC в Go — неблокирующий concurrent mark-and-sweep с триколорной маркировкой.

Фазы

  1. Mark Start — короткий STW.
  2. Concurrent Mark — параллельная маркировка.
  3. Mark Termination — короткий STW.
  4. Concurrent Sweep — очистка мёртвого.
Триколор
Цвет Смысл
БелыйЕщё не проверен, кандидат на удаление
СерыйСам проверен, ссылки ещё нет
ЧёрныйОбъект и ссылки живые

Write barrier: если чёрный объект получает ссылку на белый, белый становится серым. GOGC задаёт целевой рост кучи, по умолчанию 100%.

14. Как устроены слайсы?

Слайс — дескриптор из трёх полей: указатель на массив, len, cap. Добавление сверх cap копирует данные в новый массив, обычно вдвое больше.

Массив и слайс
Аспект Массив Слайс
Размер [3]int []int
В функцию Копируется целиком Копируется дескриптор
Сравнение == Только с nil

15. Как устроена map?

Map — хеш-таблица с бакетами. Бакет держит до 8 пар. Переполнение даёт цепочку. Ресайз инкрементальный: старые бакеты эвакуируются постепенно. Итерация рандомизирована — на порядок рассчитывать нельзя.

16. Как устроены строки?

Строка — неизменяемая последовательность байт: указатель и длина. Кодировка по умолчанию UTF-8. Неизменяемость позволяет делить память. Любая «правка» — новая строка.

17. Как устроены интерфейсы?

Интерфейс — два указателя: tab (тип и таблица методов) и data (значение). Ловушка: nil-интерфейс не равен интерфейсу, в котором лежит nil-указатель конкретного типа — tab уже заполнен, поэтому iface != nil.

18. Что такое data race и как её обнаружить?

Data race — одновременный доступ к одной памяти из нескольких горутин, и хотя бы одно обращение — запись. Ловят флагом -race. Лечат каналами, sync.Mutex / RWMutex, атомиками.

go run -race main.go
go test -race ./...

19. Что такое sync.Pool?

Пул объектов для повторного использования. Снижает давление на GC при короткоживущих буферах. Объект из пула GC может выкинуть в любой момент — на наличие рассчитывать нельзя.

var bufPool = sync.Pool{
    New: func() any { return make([]byte, 1024) },
}
buf := bufPool.Get().([]byte)
bufPool.Put(buf)

20. Как работает context?

Пакет context отменяет работу «вниз по дереву», ставит дедлайн и редко носит значения. Ключи для WithValue должны быть сравнимыми и не строками из чужого пакета.

Функции context
Функция Зачем
WithCancelКонтекст и функция отмены
WithTimeoutОтмена через интервал
WithDeadlineОтмена к моменту времени
WithValueРедкие данные запроса, не конфиг

21. Что такое линкинг времени выполнения и как init() связан с этим?

Перед main рантайм рекурсивно инициализирует импорты, считает глобальные переменные и вызывает init. В пакете их может быть несколько — в порядке объявления. Явно вызвать init нельзя.

Быстрая шпаргалка

Ключевые ответы
Тема Короткий ответ
Горутина~2 КБ стека, планирует рантайм
Буфер каналаБлокирует при полном или пустом
nil-каналВечная блокировка; close — panic
ПланировщикM:N, work-stealing, 1.14+
МодельCSP
GCТриколор, concurrent mark-and-sweep
СлайсУказатель + len + cap
MapБакеты, инкрементальный ресайз
СтрокаНеизменяемая, UTF-8
Интерфейсtab + data
deferLIFO
data race-race
sync.PoolПул, GC может выкинуть
contextОтмена вниз по дереву
init()До main, явно не вызвать

На раунде чаще всего: почему десятки тысяч горутин, буфер vs без буфера, nil-канал, фазы GC, слайс/map/iface под капотом, data race и context.

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

Нажмите на вопрос — ответ откроется ниже.

Нет. Это легковесная единица рантайма. Модель M:N, стек около 2 КБ, планирует Go, не ядро.

Отправка и получение блокируются навсегда. close(nil) даёт panic. Это не ошибка компиляции.

Нет. Если в интерфейсе лежит nil-указатель конкретного типа, tab заполнен, и iface != nil.

Порядок намеренно рандомизирован. Код, который ждёт стабильный обход, ломается на раунде и в проде.

Нет отдельного симулятора Яндекса или Авито. Есть мок и квиз. Бот @it_careergym_ru_bot — канал мэтча, не ментор «как в FAANG». Оффер не обещаем.

Что дальше

Теория Go — не экзамен на зубрёжку полей hchan. Нужно выбрать инструмент и объяснить, почему канал, а не мьютекс. Дальше — код вслух, алгоритмы и System Design. Это подготовка, не трудоустройство.

Пока слот не открылся

Соберите заявку на мок и закройте одну тему в квизе. Оффер мы не выдаём — формулировки к доске подтянуть можно.

Создать аккаунт → Найти напарника Экспресс-квиз

← Вернуться к списку статей

Также по теме: Собеседование в Авито · Теория алгоритмов · Теория System Design · Парный мок · Плейбук последней недели

Рассылка

Подписываясь, вы соглашаетесь с политикой обработки персональных данных.