Comments 4
Собственно ничего не понял, что автор хотел сказать этим сообщением на реддите и уж тем более не понимаю зачем это репост на хабр.
Обычно такие вопросы задают в чате про Go где-нибудь в телеграме или слаке, а не тут.
- В каком случае он не останавливается? Если при
ticker.Stop()
дожно останавливаться, в примере из документации так и написано:defer ticker.Stop()
. Более того, там еще и словами написано: "Stop the ticker to release associated resources". Или вы что хотите чтобы он сделал? - Приведите пример, о чем пишите. Thread-safety означает, что тип позволяет использовать определенную операцию параллельно, не боясь словить панику при одновременной записи или чтении, например, а не то, что можно использовать разные операции в каком угодно порядке. Это ничего не говорит о том, что если состояние было изменено в одной горутине (например, канал закрыт), то это не аффектит другие места.
- Если не сказано другого,
sync.Mutex
относится к полю структуры, идущему сразу же за мьютексом. Не помню, где конкретно про это написано, но теперь вы знаете.
В целом ничего из этого не является проблемой Go как языка. Конкурентные программы — сложная тема, и нужно хорошо понимать, что и зачем делается, чтобы не выстрелить себе в ногу. Go, по сравнению с другими языками, и так делает конкурентность простой и ванильной. Но полностью думать за разработчика компилятор пока не научился, отсюда и проблемы.
P.S.: документация в го очень хорошая и подробная, также не забывайте про примеры в документации (которые есть исполняемые тестовые файлы) и про юнит тесты тоже.
Еще много полезного есть в блоге, особенно там хорошо разжевано то, что касается конкурентности, мьютекстов и всего такого "сложного" для новичка из однотредовых языков.
Не останавливается, если в коде забыта строчка с defer. Тут вопрос не в том, что написано в документации: даже если ты это знаешь, очень легко про это забыть и не вставить defer в код. Ни один линтер это не ловит, насколько я знаю.
Пример наобум из godoc. Если в комментарии к типу написано просто что он "safe for concurrent use", и к нему определена куча методов, то это скорее всего нельзя воспринимать никак кроме "все методы можно вызывать параллельно друг с другом", потому что если сократить до вашего определения, тип скорее всего станет неюзабельным. Короче говоря, идея в том, что было хотя бы указано, какие методы читающие, а какие мутирующие, и какая конкурентность (1-N) поддерживается для тех и других.
Опять же, дело не в соглашениях, а в том, всегда ли разработчики следуют им на практике.
Мне кажется, в посте вам померещился наброс на язык Го, хотя это не так. Я хочу определить моменты, на которые следует обращать внимание при код-ревью, и сделать чек-лист. Я сделал раньше такой чек-лист для Java, который в десятки раз больше, что как бы говорит о том, что в Го сложнее допустить ошибку с конкурентростью, чем в Java. Однако, я все же сомневаюсь, что пунктов действительно всего три (или ни одного, — вы же ни с одним из моих пунктов не согласились), т. е. никаких типичных ошибок с конкурентностью в Го вовсе не существует.
- Смысл не в
defer
а в том, что тикер нужно остановить, иначе он будет бесконечно крутиться. Это логично, но если для кого-то не очевидно, то есть в доках.defer
помогает только в том, чтобы выполнить его гарантированно при выходе из функции, а так можете где угодно вызывать, главное, чтобы он был вызван. Некоторые линтеры проверяют вызов функций Close(), кстати. - "safe for concurrent use" подразумевает вызов функций как таковых, а не относительной последовательности. Если вы закроете thread-safe канал в одной рутине, а в другой будете в него писать — будет паника, и это ожидаемо.
- зависит от разработчика, для этого и делается кодревью.
В го легко допустить ошибки с конкурентностью — потому что конкурентность в принципе совсем не такая, как кажется на первый взгляд. Возможно есть какие-то чеклисты, можете составить свой.
Golang blog вам в помощь, можете начать отсюда, отсюда, отсюда и отсюда.
Проблемы с конкурентностью, которые вы регулярно замечаете в коде на Го?