Підготовка до співбесіди · IT та розробка

Питання на співбесіді Go-розробника

Питання на співбесіді Go-розробника: горутини й канали, інтерфейси, дженерики, обробка помилок, context, продуктивність і мікросервіси. Для Junior, Middle і Senior — з прикладами відповідей.

Популярні теми

Junior Основи Go

Чим слайс відрізняється від масиву?

Приклад відповіді

Масив має фіксовану довжину, яка входить у тип: [3]int і [4]int — різні типи. Слайс — це «вікно» на масив: вказівник, довжина й ємність.

При append понад ємність Go створює новий масив і копіює дані, тому після append слайс може вказувати на іншу пам'ять. Через це два слайси, отримані з одного масиву, можуть несподівано змінювати дані один одного.

Junior Основи Go

Як у Go обробляють помилки?

Приклад відповіді

Помилки — звичайні значення, які функція повертає останнім результатом: result, err := doSomething(). Їх перевіряють явно через if err != nil.

Контекст додають обгортанням: fmt.Errorf("load user %d: %w", id, err), а перевіряють через errors.Is і errors.As. panic використовують лише для справді неможливих ситуацій, а не для звичайних помилок.

Junior Конкурентність

Що таке горутина?

Приклад відповіді

Горутина — легкий потік виконання, яким керує рантайм Go. Запускається через go f(), займає кілька кілобайтів стека і може бути створена тисячами.

Важливо: main не чекає на горутини. Для очікування використовують sync.WaitGroup або канали, а для обмеження кількості паралельних задач — semaphore чи errgroup з лімітом.

Junior Основи Go

Як працюють інтерфейси в Go?

Приклад відповіді

Інтерфейси в Go реалізуються неявно: тип задовольняє інтерфейс, якщо має всі його методи, без implements.

Прийнято оголошувати маленькі інтерфейси на боці споживача: якщо функції потрібно лише читати, вона приймає io.Reader. Це спрощує тести — можна підставити фейкову реалізацію.

Middle Конкурентність

Чим буферизований канал відрізняється від небуферизованого?

Приклад відповіді

Небуферизований канал синхронізує відправника й отримувача: відправка блокується, доки хтось не прочитає. Буферизований (make(chan T, 10)) дозволяє покласти до N значень без очікування.

Буфер не вирішує проблем дизайну: якщо споживач повільний, він лише відкладає блокування. Канал закриває відправник, читання з закритого каналу повертає нульове значення, а відправка в закритий — panic.

Middle Конкурентність

Навіщо потрібен context.Context?

Приклад відповіді

Context передає скасування, таймаути й значення рівня запиту через ланцюжок викликів. Якщо клієнт закрив з'єднання або минув таймаут, усі запити до БД і сервісів, що використовують цей context, теж скасуються.

Правила: context — перший параметр функції, його не зберігають у структурах, а context.WithValue використовують лише для даних запиту (trace ID), а не для параметрів бізнес-логіки.

Middle Конкурентність

Як знайти й виправити race condition?

Приклад відповіді

Запустити тести або сервіс із прапорцем -race: детектор покаже місця одночасного доступу до пам'яті без синхронізації.

Виправляють через sync.Mutex / RWMutex, атомарні операції (sync/atomic) або передачу володіння даними через канали. Типова пастка — запис у мапу з кількох горутин: звичайна map не потокобезпечна, і Go може аварійно завершити програму.

Middle Основи Go

Коли варто використовувати дженерики?

Приклад відповіді

Дженерики (з Go 1.18) корисні для узагальнених структур даних і функцій над колекціями: Map, Filter, кеш, черга з пріоритетом. Стандартна бібліотека вже має пакети slices і maps, а з Go 1.23 — ітератори (range over func).

Не варто додавати дженерики «про запас»: якщо достатньо інтерфейсу або конкретного типу, код буде простішим.

Senior Продуктивність

Як ви шукаєте проблеми продуктивності в Go-сервісі?

Приклад відповіді

Профілювання через pprof: CPU-профіль, heap, алокації, горутини, блокування. У сервісі підключають net/http/pprof на внутрішньому порту.

Типові знахідки: зайві алокації в гарячих циклах, конкатенація рядків, неправильне використання sync.Pool, витоки горутин, що чекають на канал вічно. Для порівняння змін — бенчмарки (go test -bench) і benchstat. Також варто налаштувати GOMEMLIMIT під ліміти контейнера.

Senior Конкурентність

Що таке витік горутин і як його запобігти?

Приклад відповіді

Витік — горутина, яка ніколи не завершиться: чекає на канал, у який ніхто не пише, або на запит без таймауту. Пам'ять і кількість горутин поступово зростають.

Запобігання: кожна горутина має зрозумілу умову завершення, використання context зі скасуванням, select з ctx.Done(), таймаути на мережеві виклики. У тестах допомагає goleak, а в продакшні — метрика кількості горутин.

Senior Архітектура

Як ви структуруєте Go-проєкт і чому?

Приклад відповіді

Немає єдиного офіційного стандарту. Поширений підхід: cmd/ для точок входу, internal/ для коду, недоступного ззовні, пакети за доменами (orders, billing), а не за шарами (models, controllers).

Принципи: залежності спрямовані до домену, інтерфейси оголошуються там, де використовуються, мінімум глобального стану. Для великих команд — чіткі межі між модулями й заборона циклічних залежностей, які Go і так не дозволить.

Senior Сервіси

gRPC чи REST для взаємодії між сервісами?

Приклад відповіді

gRPC дає строгий контракт через protobuf, генерацію клієнтів, бінарний формат і стрімінг — зручно для внутрішніх сервісів з високим навантаженням. REST/JSON простіший для налагодження, зовнішніх клієнтів і браузерів.

Важливі аспекти незалежно від протоколу: версіонування контракту, таймаути й повтори з backoff, ідемпотентність, трасування (OpenTelemetry). Часто роблять gRPC всередині й REST або GraphQL назовні.

Типові помилки кандидатів

  • Ігнорувати помилки через `_` або логувати й повертати одну помилку двічі.
  • Запускати горутини без умови завершення й без обробки помилок.
  • Тягнути в Go патерни з Java: величезні інтерфейси й фабрики фабрик.
  • Не знати про `context` і таймаути в мережевих викликах.
  • Оптимізувати без профілювання і бенчмарків.

Як підготуватися

  • Повторіть слайси, мапи, інтерфейси й обробку помилок — це база будь-якої співбесіди.
  • Потренуйтеся писати конкурентний код: worker pool, fan-out/fan-in, graceful shutdown.
  • Запустіть pprof на власному проєкті, щоб упевнено говорити про профілювання.
  • Ознайомтеся з новими можливостями останніх версій Go: ітератори, маршрутизатор net/http.
  • Будьте готові пояснити, чому ви обрали Go для своїх задач.

Актуальні вакансії: Golang Developer

Схожі професії

Перевірте знання перед співбесідою

Випадкові питання, таймер на кожну відповідь і розбір помилок наприкінці. Можна пройти кілька разів — питання щоразу інші.