Конкурентность в Go: просто запустить — сложнее управлять
Go предлагает удобный механизм конкурентности, позволяющий запускать задачи максимально просто — достаточно добавить go перед вызовом функции, и она начнет выполняться параллельно с основным потоком. Однако для эффективного использования такого кода важно правильно управлять синхронизацией: собирать результаты, обрабатывать ошибки и учитывать возможные сценарии выполнения. На практике этому аспекту часто уделяют недостаточно внимания.
Полезные материалы о конкурентности в Go можно найти в блоге Дейва Чени. Он рассматривает различные решения в Go, объясняя их происхождение и способы использования. В своих статьях он также подробно разбирает тему конкурентности.

Например, в статье Curious Channels Дейв Чени описывает два важных свойства каналов в Go:
Закрытый канал не блокируется. После закрытия в него нельзя отправлять данные, но можно читать. Если данных нет, возвращается нулевое значение. Это удобно при использовании range, который автоматически завершает цикл.
Закрытие канала уведомляет все горутины. Вместо того чтобы отправлять сигнал каждой горутине, достаточно закрыть канал — все ожидающие горутины получат сигнал завершения.
В отличие от языков вроде C, где конкурентность управляется через блокировки и разделяемую память, в Go используются более простые и безопасные механизмы. Однако работа с каналами требует понимания нюансов.
Владислав Белогрудов, эксперт по разработке ПО в YADRO, собрал полезные материалы про конкурентность в Go. В статье — блоги, выступления и книги, которые помогут разобраться, как в Go работать с горутинами и каналами без хаоса и дедлоков.