Что можно и что нельзя делать с потокобезопасностью каналов?
Каналы в Go сами по себе потокобезопасны: из разных горутин можно одновременно отправлять в них и читать из них без дополнительных мьютексов и использовать конструкцию select для работы с несколькими каналами.
Нельзя писать в закрытый канал (это паника), небезопасно пытаться закрывать один и тот же канал из нескольких горутин, а также полагаться на канал как на защиту для любых разделяемых данных вне самого канала без дополнительной синхронизации.
Канал — это синхронизированная структура данных: внутри рантайма Go он уже защищён примитивами синхронизации, поэтому операции отправки (ch <- v) и получения (<-ch) из нескольких горутин потокобезопасны и не требуют от вас явных мьютексов вокруг самого канала.
При этом потокобезопасность канала не решает всех проблем конкурентного кода:
sync.Map и т.п.);ok == false, а операции с nil-каналом навсегда блокируются.Поэтому обычно канал закрывают в одном контролирующем месте, не пытаются закрывать его из всех отправителей, а для защиты сложных общих структур данных дополняют каналы другими средствами синхронизации.
Отметьте свой прогресс