Черновик: страница не показывается в списке статей и закрыта от поисковиков. Чтобы опубликовать, убери draft: true и пересобери.
  1. Главная
  2. Статьи
  3. 15 вопросов с собеса на Middle Go

15 вопросов с собеса на Middle Go

Артём Романович 4 мин чтения
собесыGoрантаймmiddle
Содержание
  1. Типы данных
  2. Конкурентность
  3. Рантайм
  4. Продакшен

Вопросы на Middle Go повторяются от компании к компании. Меняются формулировки, но проверяют одно: понимаешь ли ты, что происходит под капотом, и можешь ли объяснить последствия для продакшена.

Ниже 15 вопросов, которые встречаются чаще всего. К каждому — короткий ответ, который можно развернуть на собесе.

Типы данных

1. Как устроен слайс и что будет при append внутри функции?

Слайс — это структура из трёх полей: указатель на массив, длина и ёмкость. В функцию она копируется целиком. Если ёмкости хватает, append пишет в тот же массив, и вызывающий код увидит изменённые элементы, но не новую длину. Если не хватает, выделяется новый массив, и связь с оригиналом теряется.

go
func add(s []int) { s = append(s, 4) }
 
s := make([]int, 3, 10)
add(s)
fmt.Println(len(s)) // 3: длина у вызывающего не изменилась

2. Почему порядок обхода map каждый раз разный?

Рантайм специально выбирает случайную стартовую позицию, чтобы никто не завязывался на порядок. Если он нужен, собери ключи в слайс и отсортируй: slices.Sorted(maps.Keys(m)).

3. Чем nil-интерфейс отличается от интерфейса с nil-указателем?

Интерфейс равен nil, только если пусты и тип, и значение. Вернёшь (*MyErr)(nil) как error — получишь непустой интерфейс, и проверка err != nil сработает.

go
func find() error {
	var e *NotFound = nil
	return e // err != nil будет true
}

4. Строка — это байты или руны?

Байты, причём неизменяемые. len(s) возвращает число байт, индекс s[i] возвращает байт, а range по строке идёт по рунам и декодирует UTF-8. Для кириллицы это разные числа.

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

5. Что происходит с каналом в разных состояниях?

Операцияnil-каналЗакрытый канал
ОтправкаБлокируется навсегдаpanic
ЧтениеБлокируется навсегдаНулевое значение, ok == false
closepanicpanic

6. Что выберет select, если готовы несколько веток?

Случайную, с равной вероятностью. Приоритета по порядку веток нет. Если он нужен, делают вложенный select или отдельную проверку перед основным.

7. Как найти утечку горутин?

Смотрим runtime.NumGoroutine() в метриках, снимаем профиль /debug/pprof/goroutine?debug=2 и ищем тысячи горутин с одинаковым стеком. В тестах помогает go.uber.org/goleak. Почти всегда причина — отправка или чтение канала без select на ctx.Done().

8. Mutex, RWMutex, atomic — когда что?

atomic — для одной переменной. Mutex — для инварианта из нескольких полей. RWMutex — только если чтений заметно больше записей и критическая секция не микроскопическая: он дороже обычного мьютекса.

9. Что будет при панике в горутине?

Упадёт весь процесс, даже если в main стоит recover. recover работает только в той горутине, где случилась паника, поэтому в долгоживущих воркерах его ставят в начале функции горутины.

Рантайм

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

Модель GMP: G — горутина, M — поток ОС, P — логический процессор с локальной очередью горутин. Число P равно GOMAXPROCS. Свободный P ворует работу из чужих очередей. С Go 1.14 горутину можно вытеснить асинхронно, даже если она крутит цикл без вызовов функций.

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

Конкурентный трёхцветный mark-and-sweep без перемещения объектов. Большая часть работы идёт параллельно с программой, короткие паузы нужны на старте и в конце разметки. Частоту сборок задаёт GOGC, а с Go 1.19 есть мягкий лимит памяти GOMEMLIMIT, который полезен в контейнерах.

12. Когда переменная уходит в кучу?

Когда компилятор не может доказать, что она не переживёт функцию: вернули указатель, сохранили в интерфейс, захватили в замыкание, размер неизвестен на этапе компиляции. Проверить: go build -gcflags=-m.

13. В каком порядке выполняются defer?

В обратном: последний отложенный — первым. Аргументы вычисляются в момент объявления defer, а не выполнения. Отложенная функция может изменить именованный возвращаемый результат, так часто оборачивают ошибки.

Продакшен

14. Зачем context и что в нём хранить?

Для отмены, дедлайнов и значений уровня запроса: trace id, данные аутентификации. Бизнес-параметры в context.WithValue не кладут: они прячут зависимости функции. Контекст передают первым аргументом и не хранят в структурах.

15. Сервис тормозит. С чего начнёшь?

С метрик и профиля, а не с гипотез. pprof по CPU и по памяти, go tool trace, если подозрение на планировщик или блокировки. Потом бенчмарк на узкое место через go test -bench и сравнение до и после с benchstat.

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

Формат работы

Выбери подходящий формат — от прожарки резюме до полного сопровождения до оффера.

Составление резюме

Адаптирую твой опыт, оформим достижения, добавлю ключевые фразы под ATS — робота, который отсеивает резюме до того, как их увидит живой рекрутер. Будем улучшать до результата.

19 000 ₽

Разовая услуга

  • Адаптация опыта под вакансии
  • ATS-оптимизация
  • Улучшаем резюме, пока HR не начинают писать каждый день
Записаться

Бесплатная консультация

Не уверен, сработаемся ли? Запишись на 20-минутный созвон — бесплатно проконсультирую и отвечу на все вопросы.

Бесплатно

20 минут созвон

  • Оценка текущего уровня
  • Рекомендации по развитию
  • Ответы на все вопросы
Записаться

Бесплатная консультация — 20 мин

Обсудим твой уровень, цели и составим предварительный план развития. Без обязательств.

1

Напиши мне

2

Созвон 20 мин

3

Получи план

Записаться в Telegram