Comments 7
Буферизированные каналы - в 95% пахнущий кусок кода, который требует убедительного обоснования
Можно читать и писать значения в массиве по индексам, если разные горутины используют разные индексы для этого.
Утверждение правильное, но я бы сказал, что опасное, особенно для новичков - надо очень хорошо понимать ref/spec и ref/mem чтобы знать, где можно (например, с доступом по индексам), а где нельзя (например, append)
Функции takeFirst и takeFirst2 в случаеlen(options) == 0 (допустимость этого варианта отмечена комментарием в коде) работать корректно не будут.
all goroutines are asleep - deadlock! потому что цикл
Там будет паника for first := range ch { return first }
будет вечным: в канал никто не пишет и он не закрыт.
Вы бы хоть описали причину проблем, а не просто демонстрировали их. В итоге новичкам ничего не понятно, а для профи ничего нового.
Спасибо за обратную связь.
А можете подсказать, что вы имеете в виду под объяснением причин проблем? Я вроде постарался везде описать, что и почему происходит, не вдаваясь в подробности и не рассказывая то, что Go разработчики уже наверняка знают. Считаете, что стоило побольше углубиться или что-то иное?
Про профи не соглашусь - все проблемы и примеры взяты из реального опыта, где разработчики среднего уровня и выше писали примерно такой код, при этом не задумываясь "а что если контекст отменится прямо тут?" и "если я использую каналы тут, к каким проблемам это приведет?". Я бы назвал их профи, но некоторые просто не задумывались о таких потенциальных проблемах, а уж тесты на такое писать вообще не каждый любит. А уж писать тесты на случаи кроме happy path - в моем опыте совсем редкость.
Мне понравилась статья. Многое знакомо, а что-то - нет. Но хорошо, что информация теперь есть в одном месте.
Уберем первый
select
, и горутина может начать делать уже ненужную работу. Уберем второй - она может начать писать в канал, в то время как будет произведен выход из функции (контекст отменен или произошла паника). Уберем третий - горутина может начать читать из канала, в то время как одна или несколько горутин не записали значение в канал (контекст был отменен или в горутине произошла паника). Добавление всех трехselect
обеспечивает более корректную работу и, что может быть более важно, более корректное завершение работы всей функции.
В статье об этом не сказано, но я думаю это стоит упомянуть: работа внутри select
происходит со случайным каналом. И если одновременно готов и ctx.Done() и какая-то запись в другой канал - то вполне вероятно, что сработает запись в канал, а не ctx.Done(). Для решения этого подводного камня есть свои способы. Поэтому реализацию работы с каналами надо выбирать под свои нужды.
Go: особенности написания конкурентных программ