Theory
Go Runtime
Чем занимается runtime в Go?
Пакет runtime
в языке программирования Go предоставляет функции для управления средой выполнения Go,
которая включает в себя управление горутинами, сборку мусора, работу с памятью и низкоуровневые операции.
Вот некоторые из основных задач, которые выполняет пакет runtime в Go:
- Управление горутинами (goroutines): Пакет
runtime
предоставляет функции для создания, управления и синхронизации горутин (легковесных потоков выполнения), напримерgo
,GOMAXPROCS
,Gosched
,NumGoroutine
и другие. - Сборка мусора (garbage collection): Сборка мусора в Go автоматически управляется средой выполнения.
Пакет
runtime
предоставляет функции для настройки параметров сборщика мусора, таких какSetGCPercent
,SetMaxStack
,GC
и другие. - Управление памятью: Пакет runtime позволяет управлять памятью в приложении,
включая аллокацию и освобождение памяти.
Он также предоставляет функции для работы с профилями памяти, такие как
ReadMemStats
. - Низкоуровневые операции:
runtime
также предоставляет функции для низкоуровневых операций, таких как работа с указателями, исполнение ассемблерного кода и доступ к системным ресурсам. - Профилирование и отладка: Пакет
runtime
содержит инструменты для профилирования и отладки приложений Go, напримерReadCPUProfile
,WriteHeapProfile
,SetTraceback
и другие.
Concurrency и parallelism
Concurrency и parallelism (medium)
Concurrency и parallelism — это два основных концепта, связанных с одновременным выполнением задач, но они имеют разные значения:
- Concurrency (конкурентность) Это парадигма программирования, в которой несколько задач выполняются в одно и то же время, но не обязательно одновременно. В конкурентной программе задачи могут выполняться в пересечении времени друг с другом: одна задача начинается, затем приостанавливается, а другая продолжает выполнение, и так далее. В Go конкурентность часто достигается с помощью горутин и каналов.
- Parallelism (параллелизм) Это фактическое одновременное выполнение нескольких задач. В параллельной программе задачи исполняются физически одновременно, при этом используются различные ядра процессора или даже разные компьютеры. В Go параллелизм достигается путем запуска горутин на разных ядрах процессора.
Какие существуют примитивы синхронизации?
- Channels: Безопасная передача данных между горутинами.
- Mutexes: Защита общих данных от одновременного доступа нескольких горутин.
- WaitGroup: Ожидание завершения выполнения горутин.
- Atomic Operations: Безопасные операции чтения и записи для общих данных.
Что такое каналы?
Channel - это примитив синхронизации между goroutines. Они обеспечивают мощный и гибкий механизм для синхронизации доступа к данным между горутинами, что позволяет избежать Data Race.
Что будет если писать в закрытый канал?
Попытка записи в закрытый канал в Go вызовет панику (panic). Это стандартное поведение в Go, которое помогает обнаружить ошибки в программе, связанные с некорректным использованием каналов.
При закрытии канала в Go он становится недоступным для отправки данных, но все данные, которые были отправлены до закрытия, по-прежнему доступны для чтения.
Что будет если читать из закрытого канала?
При попытке чтения из закрытого канала в языке Go произойдет следующее:
- Если в канале еще остались данные, которые были отправлены до его закрытия,
операция чтения вернет эти данные вместе с флагом, говорящем о том закрыт ли канал, в значении
false
. То есть операция чтения завершится успешно, и данные будут прочитаны. - Если в канале нет больше данных, и он был закрыт, операция чтения вернет нулевое значение для типа,
который хранится в канале, и флаг, говорящий о том закрыт ли канал, в значении
false
. Таким образом, можно будет определить, что канал закрыт.
Что будет если писать в nil канал?
В языке Go запись в nil канал вызовет блокировку (deadlock) программы, что может привести к её зависанию или панике.
Это происходит потому, что запись в канал должна ждать, пока другая горутина прочитает данные из него,
но так как канал не инициализирован (nil
), нет возможности считать данные из него.
Что будет если читать из nil канала?
Попытка чтения из nil канала в языке Go вызовет блокировку (deadlock) программы,
что может привести к её зависанию или панике.
Это происходит потому, что операция чтения из канала должна ожидать появления данных в канале,
но так как канал не инициализирован (nil
), нет возможности прочитать данные из него.
Что будет если закрыть закрытый канал?
Каналы в Go могут быть закрыты только один раз. Попытка повторного закрытия канала приведет к панике. Это сделано для обеспечения безопасности и избежания непредсказуемого поведения в программе.
Another
Что такое горутины в Go и как они соотносятся с потоками операционной системы?
Basic:
- Легковесность
- Переключение происходит на уровне приложения (user space)
- Знает про
GOMAXPROCS
- Знает про M:N модель
Advanced:
- Знает точки переключения контекста
- Знает о том, что горутина, исполняющая блокирующий системный вызов, оккупирует отдельный поток ОС
- Знает размер стека новой горутины (хотя бы порядок)
- Знает про дорогостоящие переключения регистров при шедулинге потоков, кол-во памяти на поток операционной системы ( порядок)
- Понимает как найти и предотвратить утечки горутин
Expert:
- Знает про шедулинг горутин рантаймом - про привязку к P, про глобальную очередь горутин
За счет чего Go позволяет работать с большим количеством сетевых соединений одновременно?
Basic
- Netpoll, неблокирующие сокеты
Advanced
- Epoll, kqueue, IOCP
- Знает преимущества epoll над select, poll
- Знает какие события в дескрипторе можно зарегистрировать
Expert
- Работал с epoll, kqueue писал свою реализацию
- Знает отличия edge-triggered от level-triggered
Что такое каналы?
Basic
- Примитив синхронизации между горутинами
- Буферизированные и небуферизированные
- Знает как работает
select
- Знает как они устроены
Advanced
- Преимущества/недостатки по сравнению с локами
- Знает что запись в закрытый канал паникует, а в
nil
channel заблокируется - CSP
Expert
- ?
Расскажите о примитивах синхронизации и зачем они нужны?
- Каналы, локи, атомики, sync.WaitGroup, sync.Cond, sync.Once ...
- Проблемы: deadlock, race condition
- Отличия Mutex и RWMutex
Что такое интерфейс?
Basic
- Набор методов, которые должен иметь тип, удовлетворяющий интерфейсу
- Пустой интерфейс
Advanced
- Знает что из себя представляет интерфейс внутри: (value, type)
Expert
- nil-интерфейс
Использование памяти
Basic
- Чем отличаются емкость (
cap
) от размера (len
) в slice и map? - Как происходит выделение памяти, если в slice не хватает места?
Advanced
- Как происходит сборка мусора?
Написание тестов
Basic
- Какие виды тестирования бывают?
- Какие виды тестирования поддерживает команда go test "из коробки"?
- Что такое моки и как их использовать?
- Какие полезные аргументы поддерживает команда go test?
Профилирование
Basic
- Сталкивался ли с профилированием Go-программ? Какие инструменты для этого существуют? Как применяются?
- Знает о доступных инструментах, pprof, trace.
- Знает когда нужно профилировать и в общем виде какую информацию можно получить при помощи профилирования
Advanced
- Профилировал, помнит какие именно вещи можно посмотреть (cpu, mutex, heap inuse_space, alloc_space, inuse_objects, alloc_objects)
Expert
- Знает как работают профилировщики, влияние включения профилировщика на производительность программы