Go поддерживает полиморфизм через неявную реализацию интерфейсов: тип подходит по набору методов. Соответствие проверяется статически, а вызов через интерфейс обычно выбирает реализацию в runtime.
Стек эффективен для значений с понятным временем жизни вызова, куча — для объектов, которые живут дольше или разделяются между частями программы. Их сочетание упрощает управление памятью.
Общее изменяемое состояние создаёт гонки, потерянные обновления, deadlock и сложные инварианты. Уменьшайте совместное владение и явно задавайте синхронизацию.
Map в Go — отображение уникальных сравнимых ключей в значения. Чтение отсутствующего ключа возвращает нулевое значение; форма value, ok отличает его от существующего.
Запускайте целевые Go-тесты с -race и разбирайте оба конфликтующих стека обращения к памяти. Race detector замечает только пути, реально выполненные в запуске.
Нужны WithCancel, проверка maxWorkers и ошибок создания запроса, отменяемое ожидание слота и возврат error. Сейчас cancel не определён, return отсутствует, а горутин создаётся по числу сообщений.
В Go есть логические, числовые и строковые типы, массивы, слайсы, структуры, указатели, map, функции, каналы и интерфейсы. Можно объявлять собственные именованные типы.
Deadlock можно получить, если две горутины захватят два mutex в противоположном порядке. Барьер делает пример воспроизводимым, без надежды на случайный scheduling.
В коде есть опасный Unlock без показанного Lock, повторное закрытие канала и гонка с отправителями. Cancel не прерывает произвольную задачу немедленно.
Проверка динамического значения при type assertion выполняется в runtime. Компилятор при этом проверяет допустимость самого выражения и используемых типов.
Обычную Go-программу можно написать без явных импортов, но это не означает отсутствие runtime в бинарнике. Стандартный toolchain включает необходимую поддержку языка.