Pull to refresh

Comments 36

Мне кажется, Go компилятор мог спокойно создавать её за меня и позволить писать thing.TimePtr = &time.Now().

Мог бы, наверное. Но там принцип:


Programs using times should typically store and pass them as values, not pointers. That is, time variables and struct fields should be of type time.Time, not *time.Time.

Недавно в целях изучения языка решил написать свой MitM-proxy на Go. В сравнении с Python 3.* — некоторые вещи на текущий момент выглядят некрасиво, к примеру нельзя сделать slice с отрицательным значением "arr[:-10]", регулярные выражения, которые не могут быть константами и благодаря "магии" внутри Go не перекомпилируются каждый раз (но для того, чтобы об этом узнать — нужно читать документацию), а также другие досадные мелочи, но есть масса преимуществ.
Во-первых — он ОЧЕНЬ быстрый (если сравнивать со стандартными библиотеками Python)!
Во-вторых — первое окружение которое очень просто настраивается (да-да — это камень в сторону venv/node_modules).
Из инструментов для комфортной работы/отладки с ним — было достаточно atom и плагина go-plus.

Во-вторых — первое окружение которое очень просто настраивается (да-да — это камень в сторону venv/node_modules).

Что может быть удобнее, чем virtulaenvwrapper + .venv файлик?
Подход go в духе, когда "будем хранить все зависимости в репе" может с практической точки зрения и простой, но в результате это выглядит хуже некуда и попытки настроить себе базовый проект у меня с первого раза превратились в страдания. Потому что переменные окружения, которые надо прописывать, а еще и нет единого стандарта пакетов.

Мне на текущий момент приходится «переключатся» между проектами. И необходимость навешивать hook'и на выполнения pip/yarn после git clone/pull/checkout меня огорчают. Особенно при смене веток «dev/beta».
ИМХО: В случае с Go — хранить зависимости в репе можно, т.к. на размер и скорость работы с проектом это влияет не существенно. А при наличии go dep в базовых утилитах к языку — придется решить и проблему стандарта пакетов и проблему с необходимостью отслеживать версии зависимых пакетов вручную. Думаю что будет здорово, если при использовании git, вместо загрузки зависимого пакета будет создаватся submodule с необходимой версией.

А если есть необходимость использовать различные ENV-спецефические окружения, то удобнее — docker/lxc…
А если есть необходимость использовать различные ENV-спецефические окружения, то удобнее — docker/lxc…

Эм… а разве для работы go не нужен GOPATH в переменных окружения? Или это уже исправили?

регулярные выражения… благодаря «магии» внутри Go не перекомпилируются каждый раз
А точно Go не перекомпилирует? Вот честно не могу найти такого в документации, наверное плохо ищу?
С другой стороны Python как раз таки имеет кеш для регулярок.
Если правильно понял код к regexp, то тип Regexp в Go — хранит кэш для регулярных выражений, а при обращении к скомпилированному регулярному выражению возвращает в горутину копию объекта типа regexpRO доступную только для чтения (для того чтобы избежать блокировки объекта).

P.S.: А у стандартной библиотеки Go — очень подробные комментарии :)
Ну… это вполне логично, что после компиляции мы получаем объект «скомпилированная регулярка» и когда ее используем, то перекомпиляции не происходит… Но ведь так во многих языках, включая Javа, Python (это про что я лично в курсе), разве нет?

Я подумал, что Вы про методы вроде `regexp.MatchString(pattern, str)`. Аналогичные методы в Python как раз имеют кеш, а вот в Go каждый раз идет полный парсинг регулярки.

PS: Судя по всему `regexpRO` имеет место быть только для упрощения реализации Copy() (все константные поля копируются легким движением руки). Ну может еще кто-то находит такой вариант более читабельным.
Сначала пишут
всё чувствуется как железобетонно надежное… Моё внутреннее чутье показывает, что это частично из-за того, что в Go нет исключений
Ну ок, допустим. Но потом
я также использовал вызовы panic() для таких вещей как вызовы к базе данных, которые «должны всегда работать»
Хм…
на самом верхнем уровне, я ловил эти паники с помощью recover() и корректно логировал их и даже добавил немного кода, чтобы отправлять стектрейс мне на почту
А, ну так конечно получается железобетонно. Не то что с исключениями.
В общем-то, пока инстанс базы данных в проекте один и по каким-то причинам работа с репликой не подходит (например, мы обновляем данные), паниковать при недоступности базы вполне нормально, если оно обернуто в recover() выше. Конечно, в большой системе так делать не надо, но для мелкого проекта сойдет.
Так-то оно так. Просто непонятно откуда тогда взялось
Кстати, об err != nil… даёт очень хорошее чувство «это реально надёжно, я корректно обрабатываю каждую ошибку»
Совершенно непонятно, какие такие «каждые» ошибки обрабатывает автор.
Все те ошибки при которых можно продолжить работу. В случае с Go есть два режима сообщения об ошибках из модуля:
1. Код возврата: тут что-то случилось, но, в принципе, ничего страшного, если нужно — можешь продолжать работу.
2. panic: всё — наш модуль «кончился» работу с ним продолжать невозможно, но если в программе есть другие модули — они могут ещё кому-то послужить.

В случае же с исключениями задача подобного «разделения обязанностей» возможена на программиста, который модулем пользуется — а он, зачастую, не знает толком: можно ли модуль как-то «спасти» или он безвозвратно испорчен.

Теоритически схема с исключениями более гибкая, на практике — это скорее мешает, чем помогает…
Все те ошибки при которых можно продолжить работу.
А кто определяет, можно ли после ошибки проолжить работу или нет? Вызывающая сторона или вызываемая?
В случае с Java'ой — вызывающая. В случае с Go — вызываемая.

Теоретически подход Java — «круче» и «гибчее». А на практике — подход Go надёжнее.
А на практике — подход Go надёжнее.
Интересно, а не могли бы Вы поснить это несколько поподробнее? Привести конретные примеры или use-case?
В случае же с исключениями задача подобного «разделения обязанностей» возможена на программиста, который модулем пользуется — а он, зачастую, не знает толком: можно ли модуль как-то «спасти» или он безвозвратно испорчен.

Модуль то как раз «безнадежно испорчен», а вот код, который его вызвал — еще «можно спасти», но об этом может знать только вызывающий программист.

Ну вот к примеру, я формирую результаты боя в игре, для каждого юзера вызываю функцию `getStat(user)` из другого модуля, ее результат для меня не смертельно важен — если для каких-то юзеров она упала, я просто выведу знаки вопроса вместо циферок. И вот на Джаве — просто словил ексепшн и вывел вопросы. А программист на Го ведь самый умный, у него упал запрос к базе, который обычно не падает и он решает запаниковать. И вот весь расчет коту под хвост.

А потому-что в Джаве хорошее, продуманное решение, а в Гоу — очередной мусор для хипстеров.
Довольно спорный вывод. В Go panic используется для сигнала об ошибке программиста, а не работы программы (кроме самых простых случаев, напр. panic(«command line argument error...»)). То есть обычно panic используется для эмуляции assert. Пришельцы из языков с поддержкой исключительных ситуаций пытаются использовать panic/recover для эмуляции исключительных ситуаций, но это не приветствуется.
А почему вы это пишете мне? Это не я сказал, что паниковать необходимо при внезапно не сработавших вызовах к базе.

И, очевидно, человек это придумал из-за крайне кривой и неудобной работы с ошибками в Гоу
Потому что я не согласен с тем, что Go — это мусор из-за отсутствия поддержки исключительных ситуаций. Полезность исключительных ситуаций вообще спорна.
google.github.io/styleguide/cppguide.html#Exceptions
llvm.org/docs/CodingStandards.html#do-not-use-rtti-or-exceptions
Ну раз уж взываете к авторитетам и привели ссылки, то не поленитесь почитать что же по ним написано:

On their face, the benefits of using exceptions outweigh the costs, especially in new projects. However, for existing code… problematic to integrate the new project into existing exception-free code...
Т.е. вообще сами по себе исключения в С++ дают пользы больше, чем вреда, и их бы использовали… Но в одной конкретной корпорации есть куча легаси C++ кода, который с исключениями совсем не дружит.

In an effort to reduce code and executable size, LLVM does not use RTTI (e.g. dynamic_cast<>;) or exceptions
Т.е. из-за размеров бинарников не используют RTTI и исключения… Ну это разумеется применимо и к статически линкуемому Go, напичканому данамическими кастами (привет interface{}). Походу именно из-за отсутствия исключений бинарники у Go получаются такими миниатюрными, а я то все голову ломал.

PS: искренне прошу, не надо приводить бессодержательные доводы аля «ну для C++ преимущества исключений перевешивают конечно, но вот для Go нет! он ведь совсем другой, не такой как все!». Уж коли приводите ссылки для С++, то давайте в этих рамках и вести обсуждение.

Непонятно, с чем вы сейчас воюеете. Спорность пользы от исключений это такая заезженная и банальная тема, что отрицать её совсем глупо. Сотни статей написаны про то, почему исключения это зло, а соотношение "польза/вред" это довольно субъективная штука, которая, безусловно зависит от реализации и языка, о котором речь.

Конкретно сейчас я воюю с искажением фактов :)

Хорошо или плохо что в Go исключения таки есть (паника), но их не принято использовать — это отдельная тема. Хорошо или плохо, что и в других языках можно пользовать кодами возврата (например возвращать Either<> в Java), но их используют куда меньше чем исключения — тоже отдельная тема.

Но когда кто-то приводит ссылку для «аргументации через авторитет» (уже само по себе не очень), но в которой еще явно белым по черному написано «в целом исключения годнота»… Ну, меня коробит.

Уж коли написано сотни статей — вот их и приводите (если они конечно адекватные) :)

Ну тогда и я повоюю с искажением фактов: комментарий serge-phi не был "аргументацией через авторитет" — ссылка была приведена для подтверждения посыла "польза исключений — спорная тема": в ссылке хорошо описаны и плюсы и минусы, что, как бы, подтверждает поинт.


И, кстати, "утверждение через авторитет" не является логической ошибкой — если "авторитет" действительно авторитет и обладает гораздо более весомым мнением, то это может быть вполне себе мощный аргумент.


Ну и да, называть паники "в Go тоже есть исключения" это как говорить "в самолете тоже есть колёса, но их не принято использовать" (подразумевая шасси). Круглая форма и похожая функция не означает, что это одно и то же.

ссылка была приведена для подтверждения посыла «пользя исключений спорная тема»
Простите, но надо быть совсем недалеким, что бы не понимать что у любой идеи/техрешения есть и сильные и слабые стороны :)

Я тоже вот например совсем не согласен, что Go мусор из-за ситуации с обработкой ошибок… Он мусор, но по иным причинам :)

Еще раз — приводите правильные ссылки и вопросов не будет (или будут, но другие). Вы сами только что сказали что их прямо «сотни», т.е. минимум 200. Думаю есть из чего выбрать :)

И, кстати, «утверждение через авторитет» не является логической ошибкой — если «авторитет» действительно авторитет и обладает гораздо более весомым мнением, то это может быть вполне себе мощный аргумент.
Ну право, одно дело когда вы обратились к авторитету а он вам «ну в твоем случае я проанализировал все… надо делать такто и такто». Но нет ведь, мы просто смотрим со стороны что наш мастер-авторитет делает. Большую часть времени не понимаем почему мастер прянял то или иное решение, он ведь нам не отчитывается и ведет большую часть работы закрыто… А потом пытаемся повторить :)
Он мусор, но по иным причинам :)

Я думаю, что называть мусором другие языки программирования, которые оказались гораздо более удачно реализованными и более популярными, чем ваш любимый язык, не делает чести вам ни как собеседнику, ни как представителю Clojure-коммьюнити. На оскорблениях хорошее коммьюнити не построишь.


Еще раз — приводите правильные ссылки и вопросов не будет

Ссылка вполне себе "правильная" — она кратко и наглядно демонстрирует и перечисляет плюсы и минусы.


Большую часть времени не понимаем почему мастер прянял то или иное решение,

Согласен.

На оскорблениях хорошее коммьюнити не построишь.
Ой какая грубая уловка в риторике попытаться противопоставить собеседника сообществу, не надо так ;)

Про мусор — это мое личное мнение. И совершенно никаим боком ни к Clojure, ни к иному языку, ни к какому либо коммьюнити не относится :)

Своим определением («мусор») я не пытаюсь никого оскоробить или принизить язык. Он во многих местах сделан клево, я его прямо щас использую. И он очень даже к месту ;)

Но в целом я считаю этот язык очень сильно переоценненым, во многом благодаря авторитету его создателей и компании, где он зародился… В целом как «опенсорсный язык, применимый для разных компаний и проектов» он для меня «мусор».
Ссылка вполне себе «правильная» — она кратко и наглядно демонстрирует и перечисляет плюсы и минусы.
Для С++. Плюсы и минусы там отнюдь не универсальные.
А Go, как известно, отнюдь не C++.
Плюсы и минусы там отнюдь не универсальные.

Автор комментария не утверждал, что они универсальные, он утверждал, что тема спорная, а не однозначная.


А Go, как известно, отнюдь не C++.

Хех, вы несколько комментариев выше сами такую аргументацию высмеивали("PS: искренне прошу, не надо приводить бессодержательные доводы аля «ну для C++ преимущества исключений перевешивают конечно, но вот для Go нет! он ведь совсем другой, не такой как все!»")

Kолёса у самолётов (не у всех, впрочем) всё-таки есть, а шасси — это слегка другое. (:


Мне тоже кажется, что языки, которые постулируют "отказ от исключений" не совсем честны в этом плане.

Я не утверждаю, что исключения — это зло, которое должно быть искоренено. Я просто говорю, что и без исключений можно жить, поэтому неправильно делать вывод о том, что язык такой-то — это мусор, потому что в нем нет исключений.
что было глотком свежего воздухе после битвы на мечах от 20 секунд инкрементальной и 20 минут полной компиляции в Scala.

Автор явно утрирует и набрасывает. Если речь идет о таком небольшом проекте, то компиляция в Scala тоже будет занимать секунды. Не знаю о каких 20 минутах с нуля и 20 секундах инкрементальной он говорит, когда лично у меня, полная перекомпиляция проекта в ~20kloc с обильным использованием имплиситов, макросов и вот этого всего + то же ранее упомянутое, переформатирование всех сорцев — занимает ~50 с. на обычном домашнем ноуте (scala 2.12.4 и sbt 1.0.3).
Стыд и срам, у меня фронтенд c вебпаком и то быстрее собирается. Проект на 32 kloc (только JS) полностью собирается в среднем за 35 секунд.
Вот именно что «собирается», а не компилируется. Сравнение из разряда «моя подлодка плавает быстрее, чем ваш мотоцикл».
Хочу заметить, что в процессе сборки происходит компиляция JS, но вдобавок происходит еще вагон и маленькая тележка операций, навроде компиляции less-файлов, оптимизации ресурсов, прогона линтера и так далее. Так что сравнение вышло из разряда «моя подлодка ездит по дорогам быстрее, чем ваш мотоцикл».
Sign up to leave a comment.

Articles