Что такое конкурентность в программировании
Что проверяют
Различаете ли вы конкурентность и параллелизм и понимаете ли модель, на которой построен язык. Вопрос звучит общо, но в Go он всегда ведёт к следующим: как устроены горутины, кто их планирует и чем вы синхронизируете доступ к общим данным.
Как отвечать
Начните с разграничения. Конкурентность это про устройство программы: задачи разбиты на части, которые продвигаются независимо и в произвольном порядке. Параллелизм это про исполнение: несколько частей физически считаются одновременно на разных ядрах. Конкурентная программа на одном ядре остаётся конкурентной, она просто чередует куски работы.
Дальше про Go. Горутина это не поток операционной системы: рантайм мультиплексирует тысячи горутин на небольшом числе потоков, стек начинается с нескольких килобайт и растёт по мере надобности, поэтому запускать их можно щедро. Сколько горутин выполняется параллельно, задаёт GOMAXPROCS.
Синхронизация в двух вариантах. Каналы передают владение данными и хорошо ложатся на схему «производитель и потребитель», select ждёт сразу нескольких источников. Там, где состояние общее и структура простая, sync.Mutex и sync.WaitGroup понятнее. Отмену и таймауты проводите через context, это единый способ остановить дерево задач.
Где спотыкаются
Отвечают «конкурентность это когда всё выполняется одновременно» и ставят знак равенства с параллелизмом. Одновременность это возможное следствие при нескольких ядрах, а не определение; на одном ядре конкурентность никуда не девается.
Запускают горутины и не думают про их завершение. Отправка в канал, который никто не читает, вешает горутину навсегда, а выход из main обрывает остальные молча, посреди работы. Владение завершением должно быть явным: группа ожидания, закрытие канала или контекст.
Считают, что каналы сами по себе защищают от гонок. Общая мапа, счётчик или срез под несколькими горутинами ломаются ровно так же, и увидеть это глазами нельзя: проверяют детектором гонок в тестах и нагрузкой, а не рассуждением.