Що питають на співбесіді у Golang розробників? В цьому тексті зібрано великий перелік поширених питань з теорії та практики для спеціалістів різних ґрейдів — Junior, Middle, Senior. Він буде корисним для підготовки до технічного інтервʼю та допоможе виявити прогалини в знаннях. Зазвичай кандидатам ставлять лише невелику частину питань із цього списку. Євген Кострика, Golang Developer у Boosters та Володимир Корнієнко, Back-end Engineer у Headway, партнерській компанії Genesis, поділилися, чим відрізняються співбесіди на різні позиції, а також пояснили, чого очікують інтервʼюери від кандидатів та на що звертають увагу.
Питання для Junior
Співбесіда для ґрейду «джуніор» зазвичай починається з низки загальних теоретичних питань. «На мою думку, це гарний спосіб почати інтервʼю. Це дає змогу зрозуміти, що ви говорите однією мовою. Наприклад, якщо кандидат не знає, що таке взагалі ООП, то, можливо, навіть немає сенсу продовжувати співбесіду, — ділиться Євген Кострика, Golang Developer у Boosters. Далі інтервʼюеру варто переходити до більш практичних питань, або таких, що корелюють з фактичною роботою, з якою стикнеться розробник. «Якось на співбесіді на попередню роботу мене протягом години «ганяли» винятково по теорії, щоби визначити мій ґрейд. На мою думку, це не зовсім обʼєктивно. Вважаю, що іноді тестові завдання можуть значно більше сказати про бекграунд розробника, ніж теоретичний квіз», — пояснює Євген.
Робота джуніорів — суцільні стресові ситуації, з якими вони стикаються майже щодня. Тому на співбесідах інтервʼюери часто перевіряють реакцію — це можуть бути завдання з лайфкодингу або доволі складні питання. «В такому випадку звертають увагу не на саму відповідь (правильна вона чи ні), а на те, як кандидат реагує на труднощі, хід його думок та мотивацію», — каже Євген Кострика.
Загальні питання
1. Які бувають типи баз даних?
2. Що таке HTTP-протокол? Як він працює?
3. Що таке статус-код у HTTP? Назвіть статус-коди, які знаєте?
4. Що таке патерн програмування? Які патерни ви знаєте?
5. Що таке процеси та потоки в операційній системі?
6. Які основні принципи ООП?
7. Що таке SOLID?
8. Поясніть, що таке Docker?
9. Що таке контроль версій і чому він важливий у розробці програмного забезпечення?
10. Опишіть життєвий цикл розробки програмного забезпечення?
11. Що означають різні фази життєвого циклу та які дії виконуються на кожній з них?
Go
12. Які переваги має Go перед іншими мовами програмування?
13. Чи можете ви пояснити концепцію каналів у Go?
14. Як в Go реалізовано ООП?
15. Що таке goroutine? Навіщо вона потрібна?
16. В чому різниця між goroutine та потоками?
17. Назвіть види лапок в Go? Чим вони відрізняються?
18. Що таке slice? Як він влаштований?
19. Чим slice відрізняється від масиву?
20. Чи потрібно передавати slice по ссилці у функцію?
21. Як передаються змінні в Go?
22. Який розмір масиву виділяється під slice при його розширенні?
23. Що таке runtime?
24. Що являють собою рядки в Go?
25. Як можна оперувати рядками?
26. Чи можна змінити певний символ у рядку?
27. Що відбувається при склеюванні рядків?
28. Як визначити кількість символів для рядка?
29. Як працює базова функція append?
30. Якщо у функції є return, чи обов'язково вона поверне те, що зазначено в return?
31. Що таке пакети в Go? Які пакети ви знаєте?
32. Як працює сортування? Які знаєте допоміжні функції для сортування?
33. Поясніть, як працює оператор defer?
34. Який порядок виконання для кількох операторів defer у Go?
35. Чим defer відрізняється від інших операторів потоку керування в Go, таких як return і panic?
36. Як ви розумієте процес garbage collector в Go?
37. Що таке асинхронність?
38. Що таке конкурентність?
39. Що таке паралельність?
40. З якими сторонніми пакетами та фреймворками працювали? Опишіть свій досвід. Чому обрали саме їх?
41. Який порядок виконання операцій case у select?
42. Що таке type switch?
43. Як повідомити компілятор, що наш тип реалізує інтерфейс?
44. Яке у slice zero value? Які операції з ним можливі?
45. Чим відрізняється int від uint?
46. Що таке типовий int і які є аспекти його реалізації?"
47. Як перетворити рядок на int і навпаки? Чи можна зробити int(string) та string(int) відповідно?
48. Що таке константи? Чи можна їх змінювати?
49. Де константи розташовані в памʼяті?
Map
50. Що таке map в Go? Чим відрізняється від інших структур даних?
51. Які є особливості синтаксису отримання та запису значень у map?
52. Як відбувається пошук по ключу в map?
53. Як додавати та видаляти пари ключ-значення з map в Go?
54. Що станеться, якщо ви спробуєте отримати доступ до ключа, якого немає в map в Go? Як це можна вирішити?
55. Чи можна зробити map з ключами різних типів у Go? Якщо так, то як це зробити?
56. Як перевірити, чи існує ключ в map? Який найефективніший спосіб це зробити?
Інтерфейси
57. Що таке інтерфейс у Go? Яке його призначення та чим він відрізняється від структури?
58. Наведіть приклад реалізації інтерфейсів в Go?
59. Як ви оголошуєте інтерфейс у Go?
60. Чи можете ви навести приклад інтерфейсу, який визначає метод?
61. Як визначити тип інтерфейсу?
62. Що таке порожній інтерфейс? Як його можна використовувати?
63. Як переконатися, що ваш інтерфейс сумісний із кодом, який його реалізує?
64. Що таке поліморфізм у Go? Як інтерфейси підтримують поліморфізм у Go?
Практичні завдання
65. Що виведе цей код? Чому? Які зміни треба внести, щоби програма вивела 42 и 13?
66. Що виведе цей код? Чому?
67. Що виведе цей код? Чому? Як його виправити?
68. Що виведе цей код? Чому? Як його виправити?
69. За який час умовно виконається програма — за 3 секунди чи за 6? Що потрібно змінити, щоби код працював за 3 секунди?
Питання для Middle
Ґрейд Middle — перехідна ланка. Тому в кандидатів так само можуть запитати теорію, дати завдання на кодинг. Від них очікують знання різноманітних нюансів горутин, тестування, синхронізації, роботи з мікросервісами та garbage collector. Також інтервʼюери часто мають спільний список питань для Middle / Senior, просто не очікують від мідла такої глибини аналізу та досвіду. Тому радимо кандидатам цього ґрейду також переглянути наступний розділ.
70. Які технічні недоліки Golang можете назвати?
71. Як зробити з масиву slice? Чи відсортується масив у сортуванні slice?
72. Припустимо, ваша функція повинна повертати деталізовані Recoverable та Fatal помилки. Як це зробити?
73. Що таке пакет testify?
74. Що таке пакет Mock? Для чого він потрібен?
75. Який мінімальний і максимальний розмір горутин?
76. Що буде, якщо розмір горутини перевищив допустимий максимум?
77. Чи однаково горутини ділять між собою процесорний час?"
78. Які є способи зупинити горутини?
79. Як налагодити зв'язок між горутинами?
80. Чи можна використовувати один і той самий буфер []byte у кількох горутинах?
81. Яка різниця між монолітною архітектурою та архітектурою мікросервісів? Наведіть приклад, коли варто кому віддати перевагу?
82. Які існують загальні стратегії кешування?
83. Поясніть концепцію рефлексії в Go. Як її використовувати для реалізації загальної структури даних або алгоритму?
84. Поясніть концепцію інтерфейсів у Go? Наведіть приклад, як ви використовували інтерфейси в проєкті, та як вони допомогли досягти ваших цілей?
85. Чи є для Go хороший ORM? Аргументуйте свою відповідь.
Канали
86. Як можна використовувати канали для реалізації паралельного програмування, і які найкращі практики для цього?
87. Яких поширених помилок слід уникати під час використання каналів у Go?
88. Як можна використовувати буферизовані канали в Go для підвищення продуктивності, і які компроміси слід враховувати при цьому?
89. Як можна використовувати оператори select для обробки кількох каналів і уникнути блокування?
90. Які є альтернативи каналам для паралельного програмування у Go? Коли можна вибрати один підхід замість іншого?
91. Що таке буферизований та небуферизований канал?
92. Назви чотири аксіоми каналу?
93. Що буде, якщо писати/читати в nil канал?
94. Що буде якщо писати/читати/з закритий канал?
95. Що буде якщо писати/читати в/з буферизованого каналу?
96. Що буде якщо писати/читати в/з небуферизованого каналу?
97. Як закрити канал? Що з ним відбувається?
Контексти
98. Що таке контекст? Для чого застосується?
99. Чим він важливий для паралельного програмування?
100. Чим відрізняється context.Background от context.TODO?
101. В чому різниця між context.WithCancel, context.WithDeadline, context.WithTimeout?"
102. Як можна використовувати контекст у Go для керування термінами та тайм-аутами?
103. Яких поширених помилок слід уникати під час використання контексту в Go?
Памʼять
104. Як реалізовано сховище пам'яті Go?
105. Що означає * і &?
106. Як передаються параметри у функцію?
107. Чи є особливості поведінки під час передачі map і slice у функцію?
108. Як функції діляться пам'яттю?
Garbage collector
109. Що таке garbage collector і за яким алгоритмом він реалізований в Go?
110. Коли запускається garbage collector?"
111. Які ресурси споживає garbage collector?"
112. Які переваги та недоліки має garbage collector?
113. Як можна налаштувати garbage collector в Go, щоби оптимізувати продуктивність і мінімізувати використання пам’яті?
114. На які типові проблеми продуктивності слід звернути увагу під час використання garbage collector?
115. Які є альтернативи garbage collector в Go для керування пам’яттю? Коли можна вибрати один підхід замість іншого?
Синхронізація
116. Що таке пакет Sync і що він надає?
117. В чому різниця між Mutex і WaitGroup у пакеті Sync?
118. Що таке змінна Once і як вона використовується в пакеті Sync?
119. Що таке пакет atomic? Як використовується в пакеті Sync?
120. Як можна використовувати WaitGroup у пакеті Sync для синхронізації виконання кількох готурин?
121. Що таке Mutex і для чого він використовується?
122. Які існують типи Mutex?
123. Яка різниця між Mutex і RWMutex у Go?
124. Чи можете ви пояснити, як Mutex допомагає синхронізувати доступ до спільних ресурсів у Go?
125. Як Mutex отримує та знімає блокування в Go?
126. Що таке взаємоблокування і як його можна уникнути, використовуючи Mutex у Go?
127. У яких сценаріях ви б використали Mutex над WaitGroup у Go?
128. Чи можна реалізувати sync.Mutex та sync.WaitGroup у каналах? У який спосіб?
Мікросервіси
129. Що таке мікросервіси? Чим вони відрізняються від монолітних архітектур?
130. Які переваги та недоліки використання мікросервісів?
131. Чи працювали ви з будь-якими фреймворками мікросервісів у Go? Опишіть свій досвід?
132. Як би ви вирішували наскрізні проблеми, такі як authentication and logging, в архітектурі мікросервісу? Опишіть моделі та інструменти, які ви б використовували?
133. Як би ви підійшли до тестування та налагодження архітектури мікросервісу? Опишіть стратегії та інструменти для виявлення та усунення проблем?
134. Як би ви впоралися з узгодженістю даних і транзакціями в архітектурі мікросервісу? Чи можете ви описати деякі шаблони та інструменти?
Тестування
135. Що таке модульне тестування? Чим воно відрізняється від інтеграційного тестування та наскрізного тестування?
136. Як написати модульний тест у Go? Наведіть приклад простого модульного тесту для функції?
137. Як ви використовуєте mocking у своїх тестах? Наведіть приклад ситуації.
138. Як ви вимірюєте покриття коду у своїх тестах? Який інструмент ви використовуєте та як інтерпретуєте результати?
139. Як ви обробляєте залежності у своїх тестах?
140. Як написати тест для паралельного коду в Go? Наведіть приклад тесту для паралельної функції?
141. Як ви автоматизуєте свої тести? Який інструмент використовуєте та як інтегруєте його з пайплайном CI/CD?
Практичні завдання
142. Дано масив n x n, поверніть елементи масиву, розташовані від крайніх елементів до середнього елемента, рухаючись за годинниковою стрілкою.
array = [[1,2,3],
[4,5,6],
[7,8,9]]
snail(array)#=>[1,2,3,6,9,8,7,4,5]
143. Дано додатне число n > 1. Знайдіть розклад n на прості множники. Результатом буде рядок такого вигляду:
"(p1**n1)(p2**n2)...(pk**nk)"
з p(i) у порядку зростання та n(i) порожнім, якщо n(i) дорівнює 1.
Example: n = 86240 should return "(2**5)(5)(7**2)(11)"
144. Реалізуйте функцію, яка отримує дві адреси IPv4 і повертає кількість адрес між ними (включно з першою, за винятком останньої). Усі введені дані будуть дійсними адресами IPv4 у вигляді рядків. Остання адреса завжди буде більшою за першу.
* With input "10.0.0.0", "10.0.0.50" => return 50
* With input "10.0.0.0", "10.0.1.0" => return 256
*Withinput"20.0.0.10","20.0.1.0"=>return246
Питання для Senior
Питання для розробників рівня сеньйор зазвичай стосуються архітектурних рішень, оптимізації, безпеки та вирішення різноманітних проблем системи. Інтервʼюер звертає увагу, які технології обирає кандидат для запропонованих рішень, як аргументує свій вибір, які бачить плюси й мінуси. Загалом від нього очікують глибокого розуміння, як працюють сучасні сервіси, та як їх будувати.
«Мова програмування Golang дизайнилася, як проста та мінімалістична. Це не С++, в якому сеньйор і мідл дуже відрізняються за рівнем знання мови. Можна сказати, що починаючи зі «strong junior» до «senior» в Golang вже немає великої різниці у якості коду. Просто сеньйор більш концептуально розуміє проблеми, має глибокі знання, як все працює під капотом, ширше бачить проблеми та може запропонувати рішення на рівні архітектури — це ми перевіряємо на System Design інтервʼю», — пояснює Володимир Корнієнко, Back-end Engineer у Headway.
145. Як можна оптимізувати роботу програми Go? Опишіть поширені «вузькі місця», з якими ви стикалися, і як ви їх вирішували?
146. Розкажіть про ваш підхід до дебагінгу в Go? Які інструменти та стратегії вважаєте найбільш ефективними?
147. Як би ви впоралися з concurrency в програмі Go? Наведіть приклад використання вбудованих функцій паралелізму?
148. Розкажіть про ваш підхід до тестування коду Go? Які фреймворки та інструменти використовуєте?