Комментарии 270
Н-р: нет функции типа IsFileExists () (ну серьезно нет)
«Чего только нет стандартной библиотеке Go, практически ничего нет»
Стандартными средствами для работы с SQL невозможно получить данные запроса полный состав которых и тип которых вам заранее неизвестен. Обработка элементарного запроса «select * from table» превратится для вас в ад по поиску костыля.
Определение видимости элемента в зависимости от кейса первой буквы отдельный гемор, что будет если вы решите поменять область видимости? Да, да…
Возвращаемых функцией кортежи нельзя на лету преобразовать тип.
func get() (int64, err) {}
i int
err error
i, err = get() // Ошибка, которую нельзя исправить в этой строке
А ещё нет директив компилятора (Ну и так далее)
Вообще, взглянув на те решения которые предлагает Go в тех или иных ситуациях (Синтаксис и прочее)
Создается впечатление, что автор языка школьник который решил изобрести свой язык. Как ещё можно объяснить такое решение для условной компиляции под разные платформы:
pkg_windows.go
pkg_linux.go
и многие, многие другие решения.
Серьезно, строить современный язык, стоя на плечах гигантов и имея весь их опыт и сделать такое? Ну блин(
пс За статью спасибо
Тут именно особенности. Например, мне жутко не нравится штука с импортами. Закомментировал кусок кода, комментируй и импорт?
Отключалось бы оно, вопросов бы не было, но…
В целом, если вам нравится, что бы за качеством вашего кода следил компилятор, то пожалуйста. Вот только тогда вам придется писать так, как хочет он.
Ну, а вот если вам приходится делать что-то, что не нравится компилятору (а такое часто бывает), то приходится страдать вам, а потом в войне приходится страдать тем, кто это читает.
К сожалению, универсальных гайдлайнов не существует именно из-за таких проблем, поэтому, обычно они и подкручиваются командами.
Как бы, вам никто не мешает поставить статический анализатор кода на входе и получить тот же результат, только с возможностью его настройки.
Ну, могу сказать, что Python и Java в целом отлично обходятся и без такого жесткого забивания в open-source пакетах и в 90% случаев код читаем и прост.
К тому же, писать комментарии, использовать грамотные названия, избегать высокой циломатической сложности и делать другие штуки компилятор не заставит.
Тут я что-то затупил, спасибо за замечание :)
Можно заменить "компилятор" на "интерпретатор" для питона, суть то все равно не поменяется. Он так же мог бы ругатся на неиспользуемые импорты и прочее.
Если вы прочитаете ветку немного выше, то сможете убедится, что я ругаю go за такой строгий и неотключаемый подход, который в целом не так уж и не обходим, что показывает качество кода на других языках без такого подхода в целом.
Скажем, если вы увидете отличный язык программирования в котором каждая строка должна будет начинатся с ":", разве вы не скажите, что это какая-то дичь?
Это как раз вопрос к тому, почему в Go нельзя отключить проверку на неиспользуемые импорты и переменные.
А вот причем тут статическая типизация, я к сожалению, не пойму.
Но с другой стороны можно найти этому логичное объяснение
У многих языков есть несколько режимов компиляции, хотя бы Debug и Release. Что мешает Go при импорте лишних пакетов выдавать warning, а ошибку компиляции оставить только для Release-варианта?
Сделать это элементарно, зато Вы смогли бы во время разработки не отвлекаться на удаление импортов, а потом почистить их единоразово, когда текущая задача уже решена.
1. Современные IDE поддерживают автоформатирование. Настройте под себя чтобы при открытии код становился таким как вам нужно. Поправьте под себя gofmt или вовсе не запускайте его — пока вы работаете один никому нет дела.
2. Если вы работаете над чем-то серьезным, в коллективе — то у вас есть git (или нечто подобное).
Простое переформатирование кода под потребности ОТДЕЛЬНОГО программиста превращает компактные ИНФОРМАТИВНЫЕ коммиты git, в котором ты ТОЧЕЧНО видишь что было изменено — в ужастные гигантские простыни, состоящие большей частью из переносов скобочек на иную строку да изменению отступов.
Та же проблема возникает из за разности стилей написания — пока глаз подстроится, проходит время. Немного. Но часто.
То есть по сути выбор только между:
или
ТЫ МЕШАЕШЬ КОЛЛЕГАМ.
или
ТЫ ПОДСТРАИВАЕШЬСЯ ПОД ЕДИНЫЙ СТИЛЬ и КОЛЛЕГАМ ОБЛЕГЧАЕШЬ ЖИЗНЬ.
Ну вот я, например, не могу читать без боли код, в котором фигурные скобки не располагаются на отдельной строке. Чем больше язык ограничивает стиль разработчика — тем хуже.
Наоборот, в идеале синтаксис должен поддерживать только один стиль написания. Остальное сразу отлавливается компилятором (или IDE уже при написании).
Например, мне жутко не нравится штука с импортами. Закомментировал кусок кода, комментируй и импорт?
Я использую редактор Atom с плагином для go и он так умеет делать.
У меня вот vim при записи автоматически удаляет или добавляет нужные импорты.
Nil interfaces, одна из самых нетривиальных подлянок
В целом, у языка есть своя идеология и она пришлась по вкусу многим.
С другой стороны, язык в целом не удобный и минимальное отклонение от его идеологии приводит к сотням костылей.
Единственное, что я никогда не смогу понять — упор на кодогенерацию и то, что в языке нет нормальных комментариев, а только метаданные.
Отклоняться от идеологии, предлагаемой авторами, вовсе и не нужно.
То, что в других языках пытаются исправить с помощью code style guide да специальных линтеров для проверки этих стилей — в golang просто жестко директивно внедрено создателями языка.
Сие экономит кучу времени именно в больших проектах.
И позволяет меньшими усилиями интегрировать код, написанный сторонними программистами (например, открытые библиотеки).
Я согласен, что та же фигурная скобка после if { может напрягать.
Но нужно себя пересилить.
Иначе, если каждый будет писать «не в ногу», то в тех же коммитах в git мы будем получать «ложные срабатывания» — всего-то один программист использует другое расположение фигурной скобки, а уже найти то, что она на самом деле изменил в коде довольно сложно.
Если у вас большой сложный проект, то все решается довольно просто — у вас точно есть CI, если у вас есть CI, у вас есть немного автотестов, которые блочат выкатку, если падают. Добавляем к ним style-check и профит. Если проект небольшой — то практика Code Review, которая все равно должна использоватся вас спасет.
Про интеграцию сторонних библиотек я уже говорил — 90% либ на Java или Python написаны хорошо и понятно, и им для этого не нужна жесткая проверка.
И опять же таки — Golang создает иллюзию защиты — он не спасает от неправильных названий, большой цикломатической сложности и быдлокода. А все его вроде как сложные и правильные ограничения перебивает кодогенерация, которой наговнокодить — раз плюнуть.
И опять же таки — Golang создает иллюзию защиты — он не спасает от неправильных названий, большой цикломатической сложности и быдлокода. А все его вроде как сложные и правильные ограничения перебивает кодогенерация, которой наговнокодить — раз плюнуть.
А вот как с этим то быть? Все равно же и для Golang нужно настраивать синтаксический анализатор, что бы такие случаи отлавливать.
Нет, я утверждаю следующее:
"У golang есть строгий, бесполезный и не отключаемый статический анализатор, который по факту не решает проблем".
И поэтому зачем он там нужен, мне не понятно. Качества кода в целом доверить ему нельзя, и в итоге он просто иногда вставляет палки в колеса.
Возможно, я не совсем понимаю, но чем именно этот компилятор заставил программистов задуматся? Так же, он все равно не убирает необходимостью Code Review и прочих проверок.
Более того, для того, что бы обойти этот компилятор, люди сделал goimport, который автоматически обновляет строку импортов и удаляет/добавляет туда строки.
Собственно, возникает вопрос — зачем?
P.S. Скорее всего, я просто плохо формулирую мои мысли, поэтому так и получается. + я таки немного люблю спросить, потому что, например, в спорах так же всплывают и позитивные стороны Go :)
Собственно, встречный вопрос — почему нет?
Если я не ошибаюсь, то Go вроде хотел быть минималистичный. Зачем добавлять в минималистический язык бесполезные вещи?
В целом, мой аргумент остается таким же: если занятся автоматизацией code style на проекте, то все равно нужно будет переделывать или значительно дополнять то, что делает компилятор.
А если не заниматся, то основные проблемы плохого кода все равно останутся.
А если взять гипотезу у том, что значительная часть этих проверок была сделана для ускорения сборки, то почему бы ее не включать по ключу --release или как-то так?
Но часть проблем плохого кода УЖЕ РЕШЕНА за вас.
И способ решения ЕДИНООБРАЗЕН по всему программисткому сообществу golang.
Code style guide возникли не просто так.
Это как Вавилонское стопотворение — пока ты говоришь на одном языке, пока ты манипулирует одинаковыми категориями в коллективе — ты работаешь намного быстрее.
Поэтому чем раньше происходит унификация и чем невозможнее её избежать — тем лучше.
golang решает известную проблему: «есть 100 стандартов, как так можно работать, давайте придумаем общий стандарт… упс — и уже 101 стандарт». golang решает это навязыванием своего видения, подобно тому, как Python учил программистов правильно делать отступы.
У меня есть опытнейший коллега (не golang, другой язык) — но после него просто невозможно работать над кодом, пока отступы не выставлены как нужно.
Если позволить людям решать все самим — мы получим скатывание 99% программного кода в полный шлак.
Собственно, в свое время язык программирования Java с его многословностью и кучей ограничений также пытался принудить программистов писать код качественнее.
К примеру, когда-то именно для этого была в Java сделана обязательная обработка/прокидываение наверх exception вплоть по всей иерархии стека вызовов в ЯВНОМ виде.
Дизайн Java пытался решить ту же задачу что и Go. Принудительно поднять средний уровень разработки. Чуть раньше такую задачу пытались решить, проектируя язык Ada.
Просто Go пытается минималистично, облегчая работу программисту, поднять уровень кодирования. Java пытался сделать это же максималистично.
Но ЗАЧЕМ лишний труд, если за вас уже решили часть задач?
Авторы golang установили минимальную планку, ниже которой язык/компилятор запрещает опускаться.
То есть просто принудительно подняли средний уровень code style.
Но ЗАЧЕМ лишний труд, если за вас уже решили часть задач?
Проблема в том, что если подходить к этому серьезно, то нужон решать другие нерешенные проблемы, во время решения которых эти проблемы решаются сами по себе.
if _, err := os.Stat("./config.ini"); os.IsNotExist(err) {
}
2. тут строгая типизация, чего вы хотели?
3. вы так говорите «такое решение для условной компиляции под разные платформы», будто это что-то плохое.
2, Хотел бы например такого: int64(i), err = get()
// для чего кортежи в языке со структурами, для меня тоже вопрос.
3. Очень плохое, те возможности которые дает банальный IFDEF в коде, во истину удивительны.
.// тут ещё вспомнил про include-ы (
1.
IsFileExists ()
Почему это должна быть отдельная функция?
if _, err := os.Stat("/path/to/whatever"); os.IsNotExist(err), одно условие, понятное вполне
2.
По поводу «select * from table»
Язык строготипизированный, поэтому результат потребуется описать, через хаки можно разобрать результат как map[string]sql.RawBytes, это не очень удобно, но, возможно, решит вашу проблему.
3.
По областям видимости
Можно подробнее описать проблесный кейс? Для каких то кейсов подойдет gorename, для других придется или ручками изменять, или надеяться на ide, но где это не понадобится?
4.
func get() (int64, err) {}
i int
err error
i, err = get() // Ошибка, которую нельзя исправить в этой строке
Тут да, Роб Пайк против сложных авто приведений, придется использовать дополнительную переменную.
5.
А ещё нет директив компилятора
Вы смотрели на ключи сборки?
Ну и вкусовщина
pkg_windows.goдля платформозависимого кода, очень неплохо
pkg_linux.go
для платформозависимого кода, очень неплохо
Думаю, тут проблема в том, что приходится делать платформозависимый и платформнонезависимый код в таком подходе.
То есть, приходится или дублировать код, или выносить весь платформозависимый код в отдельные файлы с продуманным интерфейсом.
Так получается, что решение в С++ как-то проще и логичнее.
qfilesystemwatcher.cpp
qfilesystemwatcher.h
qfilesystemwatcher_fsevents.mm
qfilesystemwatcher_fsevents_p.h
qfilesystemwatcher_inotify.cpp
qfilesystemwatcher_inotify_p.h
qfilesystemwatcher_kqueue.cpp
qfilesystemwatcher_kqueue_p.h
qfilesystemwatcher_p.h
qfilesystemwatcher_polling.cpp
qfilesystemwatcher_polling_p.h
qfilesystemwatcher_win.cpp
qfilesystemwatcher_win_p.h
В целом, правильнее будет сказать что в С++ может применятся такой подход.
В других библиотеках вместо этого используют IFDEF, например, в случаях, когда необходимо поменять только небольшой кусок поведения большой функции или прочее.
Наверное, вы меня не поняли. Я говорю про то, что существуют и эффективно используются другие подходы на ряду с этим.
В случае QT такое разбитие кода походит из-за архитектуры.
А что делать в случаях, когда, например, нужно подключать разные библиотеки работы с консольными окнами в зависимости от платформы?
И это, знаете ли, хорошо. Рискну предположить, что вы не видели С/С++ библиотек, состоящих из #ifdef
наполовину и более.
Видел. Для непривычного глаза — дичь дикая, разобратся сложно, особенно, если не знаешь что означают все эти переменные.
Рискну предположить, что люди, которые с этим работают как-то привыкли.
Но суть посыла в том, что такой подход не обязательный и люди могут использовать другой. А вот на Go — нет.
if _, err := os.Stat("/path/to/whatever"); os.IsNotExist(err)
vs
if FileExists("/path/to/whatever") {}
Правда не понятно почему? (И это я только один пример взял первый пришедший в голову)
2. «Язык строготипизированный» это совсем не объяснение. Костыли и не достаточно проверенные решения типа sqlx — превращают Go в СтрогоВелосипедизированный язык
4. Это непродуманность языка.
5. x:={ifdef windows}5{elseif linux}1{endif} — вот это очень неплохо
а если речь про кастомные определения, позволяющие управлять кодом, эх!
«но где это не понадобится» — вот поэтому я называю автора языка школьником не имеющим достаточного опыта, для того, чтобы понять, где это понадобится.
Очевидно, в микросервисах практически не нужна платформозависимая работа. Немного примеров о том, где может приходится IFDEF:
- Работа с графическим окружением. Там, добавление иконки в трей, отрисовка на экране, вывод алертов и прочее.
- Работа с сложными вычислениями для разной архитектуры\
- Работа с графическими движками или просто поддержка нескольких графических оболочек (например, QT/GTK) при компиляции.
- Кроссплатформенные консольные утилиты, которые требуют работы с системой.
То есть, вы согласны с тем, что Go — язык не универсальный с ограниченной зоной применения ну или разрабатывался таким?
Но в самом языке многое напрягает, о чем я пишу.
Почему бы Фольксваген не сделать лучше, а не залазить каждый раз в салон через багажник?
Думаю, что это последствия активного рекламного продвижения Golang во все места, в которые можно и нельзя.
Я все еще помню эти шикарные success статьи про то, что ребята переписали микросервисы с tomcat+java на go и получили 10-кратный прирост в силе. А их тогда были десятки.
Это слишком было похоже на такое продвижение.
Вы считаете, что никто не занимается маркетингом Goland, как языка? Маркетологи есть у каждого популярного языка и он так и иначе продвигается в массы, потому что иначе умирает.
За чьи тогда деньги организовывают конференции? За чьи деньги маркетологи продвигают Goland как язык, который решает проблемы с поддержкой качества кода (которые уже были решены и до него)?
Глупо отрицать, что маркетинга у Goland нет.
P. S. Писать на Go никто не заставляет, но я же могу критиковать продутк, которым мне предлагают попользоватся?
КОМУ это надо?
В отличие от .NET — golang совершенно некоммерческий.
Есть добровольческий евангелизм тех, кому golang нравится,
не путайте с коммерческим маркетингом (market — это рынок по английски)
Сразу нагугли три конференции:
http://golanguk.com/
https://gophercon.com/
http://www.dotgo.eu/
Вот если зайти в список спонсоров — можно сразу понять кому. Язык может быть некоммерческим только в одном случае — если у него конференций или нет.
Спонсоры хотят ЗАСВЕТИТЬСЯ там, где куча профессионалов собирается.
Особенно засветится хочет google :)
В целом, цепочка работает так:
- Google разрабатывает что-то на golang.
- Ему нужно сообщество вокруг golang, что бы он развивался.
- Он спонсирует разработку и вкладывается в маркетинг, что бы больше людей начало его использовать.
Современный мир IT работает именно так.
Google вкладывает средства в разработку языка по доброте душевной?
Google язык вовсю использует.
Уже очень давно.
Он первый пользователь языка.
Он вкладывается в СВОЙ СОБСТВЕННЫЙ ИНСТРУМЕНТ.
При чем здесь душевная доброта?
Собственно и по некоторым замечаниям разработчиков понятно — они часто говорят «нам так надо, нас так устраивает». Например, про вендоринг — «нас устраивает, внутри Гугля есть своя система вендоринга, для массового потребления она не годится, кто хочет — пишите свою».
Вы правда не замечаете некоторой противоречивости утверждений "golang совершенно некоммерческий" и "Он вкладывается в СВОЙ СОБСТВЕННЫЙ ИНСТРУМЕНТ"?
Если у вас на рабочем месте стоит удобное кресло — то какое отношение это кресло имеет к сайтам на 1С-Битрикс, которые вы создаете с коммерческой точки зрения?
Ваш коммерческий интерес — в создаваемых вами сайтах.
А вовсе не в кресле.
В огороде бузина, а в Киеве дядька.
Во-первых, кресло в офисе удобное ровно по одной причине — это может потенциально улучшить эффективность и лояльность сотрудников, что потенциально может повысить прибыль. Вот вам коммерческий интерес удобных кресел.
Во-вторых, ситуация такова, что golang контролируется Google, а его разработка ведется со вполне определенной целью — повысить эффективность сотрудников Google, использующих его в работе.
Так что аналогия с креслом тут никак не применима.
Кресло такой же инструмент повышения производительности труда. НЕ ПРИВЯЗАННЫЙ к технологиям Гугля, как и язык программирования.
Вот пример Apple с его Swift или Objective C — это да.
Тут если хочешь писать под OS X или iOS — намного проще это делать на языках, развиваемых Apple.
С golang — нет жесткой завязки под сервисы Гугля. Нет требований сервисов использовать именно golang.
Поэтому я и утверждаю — язык golang привязан на коммерческий интерес Гугля не более, чем кресла, которые используют сотрудники Гугля.
Такие же кресла и тот же язык программирования — их могут использовать кто угодно. Ограничений при создании веб-сервисов нет никаких.
Нет привязки к Гуглю, нет монопольного требования использовать только golang на сервисах Гугля — нет и коммерциализации.
Golang + Google такая же связка как C#/.net Core + Microsoft. Тоже вроде как open-source в Github, но все то понимают, кому принадлежит основной актив и разработка языка/экосистемы.
И лучше бы этот кто-то зарабатывал бы очень много и имел бы достаточно времени и достаточно опыта.
Так что какая разница кто ему платит (если это не лично ты из своего кармана), если язык УЖЕ СУЩЕСТВУЕТ, если ОН УНИВЕРСАЛЕН.
Касаемо golang 1.7, к примеру:
в релизе приняли участие 170 человек,
из которых 140 — НЕ ИЗ Google.
2. Разница в том, что центр языка не какой-то фонд, а компания. Следовательно язык будет развиватся так, как выгодно компании.
Главный разработчик запрещает вам лично писать/использовать сторонние библиотеки?
И не надо чтобы язык развивался кто в лес кто по дрова. Язык программирования это слишком фундаментальная вещь, чтобы позволять людям без опыта его лабать.
А какой достаточно развитый язык развивался децентрализовано?
C# — Microsoft
Python — Google; кое-какая свобода дала две плохосовместимые версии, в результате полмира уже много лет как сидит на Python 2, хотя Python 3 уже зрелый.
Golang — Google
Delphi — Borland
Java — Sun, Oracle
Rust — Mozilla централизовано его разрабатывает, в своих целях.
Ruby — там там вообще один разработчик, в результате чего и скорость компилятора не успевает поднять, хотя знает как, нет времени.
С++ — получили зоопарк компиляторов и стандартов. Если на Golang или Python компилиться с полпинка, то для С++ умение написать так, чтобы компилилось везде или умение адаптировать, чтобы скомпилировалось под конкретную систему — это отдельное умение.
Мы говорим о том, что golang — коммерческий язык. А вы тут начали обсуждать пути и развитие языков.
Коммерческим можно было МНОГО ЛЕТ НАЗАД назвать C#.
Коммерческим можно назвать язык 1С.
Большая же часть языков — некоммерческая.
golang — не более чем кресло или удобная мышь сотрудника Google.
Да, он позволяет Google делать больше бабла за счет большей производительности труда и меньшей нагрузки на сервер.
Но точно так же такое же кресло и такую же мышь можно без каких либо отчислений Google использовать для создания продукта, конкурирующего с Google.
Так что он — некоммерческий.
А всего лишь — внутренний продукт, предназначенный для повышения прибыли.
Внутренняя эффективность компании — это отнюдь не коммерция.
Это зависит от ваших намерений относительно молотка.
Если вы планировали с его помощью увеличить доход или снизить затраты, то это самая настоящая коммерческая разработка.
Если цель была в получении новых знаний, то тогда разработка была бы исследовательская.
Еще бывает благотворительность, там цель — передача некоторых ценностей третьим лицам (в случае, если лица оказались не третьи, этим всем могут заинтересоваться органы).
Бывают смешанные случаи, скажем, более того, большая часть компаний большую часть своих продуктов (даже внутренних) разрабатывает хотя бы отчасти с коммерческими целями.
Тут, конечно, можно начать рассуждать о разработке некой группой, где не все участники планируют применять продукт разработки в коммерческих целях. Но тут нужно смотреть уже по отдельным участникам.
Так что, молоток для чего нужен?
Возвращаясь к golang, Google, очевидно, контролирует разработку языка, а цель разработки явно далека от чистого исследования или от благотворительности.
1. Любое удобное кресло или цветы в горшочках в офисе — в конечном итоге ради увеличения производительности труда, то есть ради увеленичения прибыли. Но это не означает, что коммерция делается за счет кресла.
Коммерция все также продолжает делаться за счет тех сайтов, которые вы делаете и продаете.
2. И хорошо, что проект golang не исследовательский.
Иначе сам golang и куча библиотек третьих лиц, написанных для golang никогда бы не стали таким развитым.
Google сделал удобное кресло.
Другие подсмотрели — и стали использовать такие же кресла.
Для увеличения производительности труда и, следовательно, прибыли.
Но коммерцию на кресле Гугль не делает.
Пример коммерции на языке программирования — это Visual Studio, .NET. MS развивала долгие годы эту платформу как специализированную под свои Windows.
golang — слишком малоспециализированная, мало заточенная на сервисы Google вещь.
Даже для коммерческого хостинга Google AppEngine язык golang — всего лишь один из многих. И появился не самым первым в хостинге.
Может дело в том, что переписав с tomcat+java на tomcat+java с 10-кратным приростом, получится покаянное письмо "какими же говнокодерами мы были"?
Дело в том, что использование tomcat для микросервисов уже указывает на такое утверждение.
2. В каком кейсе вам нужно получить «получить данные запроса полный состав которых и тип которых вам заранее неизвестен»? Когда вам нужен велосипед, вы используете велосипед. Еще раз, то можно сделать, и да, после динамических языков, это будет очень неудобно, и это нормально.
4. Это привычки из нетипизированных языков.
5. Опять же вкусовщина, мне кажется, что проще иметь отдельный файл, который содержит все «платформозависимые» фичи. + если уж хочется что то такеого есть runtime
вот поэтому я называю автора языка школьником не имеющим достаточного опыта, для того, чтобы понять, где это понадобится.
Я попросил привести кейс, если вы используете инкапсуляцию, у вас не будет проблем
Более того, это вполне удобно (хотя конечно, не так просто делается, как запрос с известным числом колонок результата).
Сначала добейся (с).
Чем плох велосипед?
Он скорее всего хуже протестирован, чем стандартная библиотека
У каждого разработчика будет свой велосипед и чужой код будет восприниматься хуже
Лишняя работа по поиску или написанию велосипеда
Он скорее всего хуже протестирован, чем стандартная библиотека
Тут не так давно (года два назад) был шикарный пост про неправильную работу алгоримтов сотрировки во многих стандартных библиотеках в некоторых крайних случаях. Так что ...
- А если произошла ошибка?
Вообще интересно стало: неужели где-то в языках на уровне драйвера DB есть встроенное ограничение на кол-во коннектов?
Описанная мной проблема возникает только при нагрузке. Если не проводить нагрузочное тестирование (да, грешен) и не знать про подобные тонкости, то предусмотреть ее практически невозможно. Поэтому я и считаю, что подобные вещи обязаны описываться в документации.
В принципе, если писать на Java, то Eclipse почти всё из вышеперечисленного в статье списка, т.е. свойственного «индусскому коду» помечает жёлтым цветом и приходится все эти «желтки» править, хотя компилятор их переварит и никто не заставляет. Т.е. если бы под GoLang был аналогичный IDE, который бы помечал бы всякий «индусский код» до компиляции, а не после, то ИМХО процесс был бы гораздо дружественным и более приятным.
В общем-то это наверное единственное, что меня не устраивает, да и то, проблему решил с помощью среды разработки, стал использовать VS Code, и вообще забыл про import, он сам автоматически формируется и при этом ещё разбивается на группы и сортируется.
А вот остановка компиляции при неиспользуемых переменных это благо, позволяет выявить ошибки в коде, навроде определения переменной в блоке, вместо присваивания, например:
a := -1; if a < 0 {a := 0}
выдаст ошибку, и убережёт от долгого поиска лишнего двоеточия, и кроме того, заставляет писать законченные куски кода, раз объявил переменную, будь добр, доделай дело.;)
Callback hell — это прежде всего свойство общепринятой методологии «как писать», свойство конкретных библиотек.
Сам язык не мешает вам использовать callback напрямую или использовать библиотеки реализующие обертку по типу await/async…
Так что нет, для работы мне не надо, а для души поищу (или подожду) чего нить другого.
предлагает некий некий новый мир, в котором прошлое исправлено и можно теперь жить по другому, красиво и изящно
Именно это он и предложил для конкурентного кода, а это как раз серверный код. И именно там Go живет прекрасно, решая проблемы, которые создавали прошлые языки. И еще спецификация языка призвана решить костыли, которые традиционно качуют в С-подобные языки. И это тоже успешно получилось исправить. Из языка вырезали весь хлам, которые есть в «мощных» языках, чтобы разработчик просто сел и написал надежный быстрый код, который легко читать, а не сидел на форумах с вопросами, а какой же способ реализации ему выбрать. Я это тоже не понимал до тех пор, пока не написал на нем несколько серверных приложений. Сложно описать, какое удовольствие получаешь от серверного Go кода на горутинах, каналах и select'ах.
Если хочется получить быстрое введение в те проблемы, которые Rust позволяет решать, советую посмотреть статью Fearless Concurrency.
Вы бы еще на JavaScript предложили посмотреть. Или Swift. Или на уже умирающий D.
Ниша у Rust совершенно другая.
Вкратце: он разрабатывался для написания сложного ПО большими группами программистов. В общем, это скучный энтерпрейз-грейд язык, не особо веселый и дружественный.
append() — инициализирует слайс, если необходимо.
Утверждение о возможности добавить значения в переменную, которая указывает на не инициализированный слайс (nil) в корне неверно.
Более того, нет такого понятия nil-слайс, есть, как я уже сказал выше, в котором не определен массив для хранения значений.
/*
Си код
*/
import «C»
Только так, с одним переносом (иначе компилятор ругается)
Запрещено использование pointer to pointer (с версии 1.6+)
Например:
var b *C.MyStruct = &C.MyStruct{}
err := C.MyFunc((**C.MyStruct)(unsafe.Pointer(&b)))
При переезде с 1.5 на 1.6 это стало довольно неприятным сюрпризом
Лучше зарекаться оскорблять неопределенные группы людей, это куда более продуктивно.
А про компилятор — в треде выше обозначили вполне понятный момент и даже пояснили, что проблема не в строгости, а в отсутствии возможности эту строгость временно уменьшить, тогда как inspections в IDE являются рекомендациями, enforce которых может происходить дальше (при релизной сборке, например), а не всегда при разработке. Это и плюс, и минус.
В том же rust компилятор ещё больше бьёт по рукам, но не за скобку, оказавшуюся не на той строке, а за потенциально небезопасные вещи, что куда лучше, но тем не менее неприятно при экспериментах с языком/новыми библиотеками и т. п.
что проблема не в строгости, а в отсутствии возможности эту строгость временно уменьшить
А зачем ВРЕМЕННО уменьшать? Вот разработчики не согласны с любым уменьшением строгости. И я с ними согласен.
Из строгого синтаксиса не следуют фашиствующий компилятор, равно как и наоборот.
И, конечно, ещё вопрос что называть строгим синтаксисом. Например, можно ли сказать, что у whitespace строгий синтаксис? Если писать для него лексер и парсер, то они будут описываться тривиальной грамматикой в ABNF/EBNF, но писать при этом на нём можно очень по разному.
За вам неиспользуемые импорты и неиспользуемые переменные? Про запас?
5,7. При беглом взгляде на код можно отличить объявление и присваивание?
6. Чем поле так отличается от переменной?
8. Почему такая разница в поведении контейнеров?
12. Чем отличается слайс от указателя на массив?
13. Неужели индекс элемента при перечислении важнее его значения?
22. Кто вообще дал такие привилегии логгеру?
7. частая проблема, пару раз очень долго разбирался с кодом, спасает metalinter, прикрутил в atom, теперь вижу все такие блоки, без подсказок может стать адом.
6. Это особенность синтаксиса, грубо говоря, слева от := могут быть только имена переменных.
8. nil это константа без типа, язык строготипизированный, чтоб не творить магии, «дефолтного» типа нет.
12. Лучше почитать в офф доке, слайс, это ссылка на массив + пара доп полей, для обеспечения динамического поведения.
13. Я думаю посыл в том, чтобы ходить по индексу, и изменять значение.
22. Это и правда ужасно, когда первый раз наткнулся на exit(1), в Fatalf, я не ожидал такого поведения, с тех пор пользуюсь другими библиотеками.
Да. И такая локаничность объявления очень удобна.
> 8. Почему такая разница в поведении контейнеров?
Ради скорости.
> 12. Чем отличается слайс от указателя на массив?
https://habrahabr.ru/post/202948/
> 13. Неужели индекс элемента при перечислении важнее его значения?
key, value или value, key? Первый порядок — логичнее.
> 22. Кто вообще дал такие привилегии логгеру?
В сложных системах используют другие логгеры.
С помощью интерфейсов они совместимы со стандартными логгерами.
Но даже если вы правы, допустим, почему в Go нет например и функции Round делающей округление?
Я на Го пробую писать всего 2 недели, написал пару серверных приложений, поэтому к экспертам себя не отнесу,
Но куда не ткни, везде тихий ужас.
Если это действительно bug/недостаток он будет исправлен.
Если это стон от недостаточной квалификации, будет получено немного опыта и боли. :)
А так же есть религиозная догма в одной из вики Golangю Примерного содержания: Если чего то нет в Go, то это ненужно, довольствуйтесь тем, что есть ибо нам виднее как нужно.
Вот 2 варианта округления: https://play.golang.org/p/Xog_9wXSqj
Один из них, самый популярный выглядит так: math.Floor(f + .5)
Вопрос, зачем для самого популярного варианта плодить сущность если он элементарен, понятен и расширяем?
Т.е. Вы предлагаете сделать что-то типа math.Round(f, 0) вместо math.Floor(f + .5)?
Ну и чем же это надо обосновывать? Не забываем про общую архитектуру (нельзя сделать значение для функции по умолчанию).
И абсолютно неправильный. Потому что по стандарту IEEE 754 для floating point при округлении -3.5 должно быть -4, а оба описанные по ссылке методы дают -3.
В этом то и суть, зачем? Сделайте math.Floor(f — .5) если округляете отрицательные значения.
Хотите универсальности? Сделайте навороченную функцию в 5 раз медленнее и на 20 строк кода.
Выбор за Вами.
Я предлагаю ввести функцию, которая делает это правильно. Если вы хотите правильно округлить число знакового типа, вам ПРИЙДЕТСЯ расширить приведенные формулы.
> В этом то и суть, зачем?
Как раз затем, что выше описаны два неправильных но очень часто используемых без знаний об потенциальной ошибке костыля.
> Сделайте навороченную функцию в 5 раз медленнее и на 20 строк кода.
А может не будем кидаться крайностями? Округление — это типичная операция.
Элементарный тест производительности представлен, вот результаты:
Round(3.5, 0): 10.0159ms
math.Floor(3.5+.5): 2.0011ms
Разница в скорости в 5 раз. Я прямо угадал. :)
Буду рад дальнейшему обсуждению по сути.
p.s. чтобы работало время, тестировать надо локально.
Т.е. Вы мотивируете отсутствие корректной реализации тем, что она медленнее некорректной?
Давайте по такому же принципу вместо сортировки будем только первые 2 элемента сравнивать, так ведь быстрее.
Скажем, на x86 реализация округления до целого оказалась даже быстрее. Вариант с указанием количества значимых цифр медленнее. Похоже, что из-за умножения и деления на степень десятки.
Пример на C# http://ideone.com/KTbHGi
Может быть из-за этого и добавляют встроенные функции для таких операций?
Вообще Go написан на Go. Так что встроенность мало чем поможет. :)
К нашей великой радости, на Go написана только каноничная версия Go. Модуль math напичкан оптимизациями под разные процессоры https://go.googlesource.com/go/+/master/src/math/, которые должны быть эквивалентны каноничной версии
1. Почему в Go должны быть вещи, имеющиеся в других языках? Почему это само собой разумеющиеся? Зачем нам вторая Java или второй С++?
Просто потому, что человечество придумало уже какие-то программные концепции — так давайте их все запихаем в очередной новый язык?
Так ведь было уже — PL/I. Им невозможно пользоваться. Так и не было создано ни одного компилятора, который поддерживает на 100% синтаксис PL/I.
Язык Go ФОКУСИРУЕТ программиста и заставляет самого брать ответственность за узкие места в программе (отсутствие remove, например, при наличии append)
Многоопытные авторы языка фокусируют вас. Да, принудительно.
Но другие многоопытные коллеги (Docker, Dropbox и пр.) проверили многоопытных авторов — и сказали — это хорошо.
2. Язык — это всего лишь инструмент. Не считаете, что он подходит — выбирайте другой.
А вот аппеляция к Docker — это зря.
Не знаю, как "многоопытные" коллеги могут каждый релиз ломать обратную совместимость и файловую систему, а потом предлагать хранить данные в контейнерах.
Дополню свой ответ тем, что у них не было особо выбора, на чем писать помимо Go. Не на С++ же.
Теперича утверждаете — что и альтернатив нет?
Юлите, меняете мнения по 100 раз на дню…
Я не помню такого, если было — ткните меня в это.
Я утверждал, что у Go есть маркетинг и методы, которым он ведется мне не нравится. Так же, я утверждал, что шквал критики в комментариях как раз из-за этого маркетинга, который пытается пропихнуть Go во все дыры. Ничего иного я не утверждал, если не ошибаюсь.
Он — бесплатный и добровольческий.
Люди освоили, испытали и — делятся опытом. Бесплатно. Это не маркетинг, это не за деньги.
Что вам не нравится?
Что люди УЖЕ освоили Golang, что он уже В МЕЙНСТРИМЕ у многих КРУПНЫХ проектов, а в ВЫ ВСЕ ЕЩЕ ДУМАЕТЕ?
Это не маркетинг. А евангелизм.
Название ничего не меняет.
Что люди УЖЕ освоили Golang, что он уже В МЕЙНСТРИМЕ у многих КРУПНЫХ проектов, а в ВЫ ВСЕ ЕЩЕ ДУМАЕТЕ?
У вас там стул впорядке? Я просто не знаю, как этот капс читать, но когда я читаю текст в голове, то получается, что вы прямо кричите.
Два года назад все осваивали javascript + nodejs. Как-то поутихло.
Евангелизм — это из опыта, из практики и совершенно бесплатно. Вам ДОБРОВОЛЬНО рассказывают, о том как у них все ПОЛУЧИЛОСЬ.
Вы в каком времени живете?
В крупных проектах уже намного более чем 2 года назад с Ноды сползли в пользу Go.
Ну или вы занимаетесь мелкими поделками — там, да, Нода только только пришла из мира «больших систем».
Я на Go уже 4-й год сижу. И уже тогда golang был в мейнстриме. У вас точно нет машины времени? Вы нам пишете примерно из 2008 года…
Окей, четыре года назад. Суть то не меняется.
Появится новый язык, вот как Go, только лучше, и все начнут переписывать вещи на него.
До того, когда я начал — я тоже долго присматривался.
Еще задолго до меня началось практическое использование Go в серьезных проектах. Он ведь от рождения создавался не как исследовательский, а как практический проект языка. Со стапелей — сразу в дело.
Появится очередной язык, который делает ЦЕЛЕСООБРАЗНЫМ переписывание — начнут переписывать.
Появился D — переписывать не бросились.
Появился Golang — тогда да, переписывать нагруженные веб-сервисы стало целесообразным.
Много лет назад (ну около 5-6) ваши слова о том, что golang — это всего лишь мода, были бы разумными.
Сейчас — уже мейнстрим, уже несколько лет как мейнстрим.
И проверенный в деле на серьезных задачах в том числе — масштабы Dropbox, Youtube, CloudFlare, Bitbucket и пр. и пр…
Это вполне допустимый путь — ведь старые версии Docker остаются доступными. Всегда можешь использовать старые, проверенные уже в продакшене.
Бекпортирование фиксов, обновление безопасности и утилит тоже обеспечили? Если нет (а оно так и есть), то и пользоватся старыми версиями тоже нельзя.
На Go написан серьезный продукт, ежедневно запускающий миллиарды контейнеров…
К тому, что называть разработчиков Docker — многоопытным, это как-то вот совсем неправильно.
То, что они написали обертку на lxc, который был не очень удобен и теперь ее допиливают — это здорово. Но проблемы Docker от этого никуда не пропадают и большинство этих проблем похожи на проблемы из-за неопытности, которая сильно сказалась на старте проекта.
А к недостаткам языка никакого. Но это же вы аппелируете к разработчикам Docker.
Тем не менее, используется прежде всего Докер, а не его клоны (вы их вообще назвать-то сможете, эти клоны? ), при том, что в инфраструктуре на базе Докера заинтересованы весьма богатые конторы — могли бы клонировать, если бы это было целесообразным.
Значит, ребята достаточно квалифицированы.
Докер — СТАНДАРТ ДЕ-ФАКТО.
А вы все пытаетесь его очернить только потому, что он написан на Go.
А вы все пытаетесь его очернить только потому, что он написан на Go.
Мне плевать, на чем он написан. Мне не плевать на его недостатки, которых море. Например, вот тут можно прочитать (часть придирок тут правда просто бред) https://thehftguy.wordpress.com/2016/11/01/docker-in-production-an-history-of-failure/
По поводу клонок и альтернативных решений — mesos, rkt, atomic и это только первое, что приходит на ум. Существенная проблема только в том, что пока они разрабатывались, ребята уже закодили Docker и теперь развлекаются. + опять же у них довольно хороший маркетинг.
Нет, потому что так и будет (я про 90%).
Но маркетинг же не делает ребят из Docker трушними программистами, которые правильно разрабатывают продукт?
1. Прикладная. Docker успешный продукт. Это уже показатель трушности, в том числе и программистов. :)
2. Теоретическая. Трушность будет только в самой хардкорной математике. Программирование не тру.
Оффтоп конечно но куда же без: немного троллинга богу троллинга и любителю троллинга. %)
Когда-то была крутая паста про Васю, который сначала сделал прототип и его продал и Петю, который долго проектировал продукт и прогорел.
Как программист Петя безуслоно лучше, но вот сделать в итоге успешный продукт у него не получилось.
2. Тут сложный вопрос. У меня действительно важный претензий в Docker только три: обновления без поддержки предыдущих решений и предупреждений о том, что «все плохо», документация и то, что управление жестким диском все на тебе (особено жесткого это в случае регистра). Поправили бы все это и был бы отличный продукт.
1. rkt — без успеха Докера никому бы и в голову не пришло лабать rkt. Это всего лишь банальный очередной виток развития, развивание темы Докера.
2. mesos — гораздо более грандиозная система, целая операционная система для датацентров. В то время как Докер — локальная система управления контейнерами.
Вы пишете о том, в чем не разбираетесь.
- Это инструмент призванный исправит недостатки Docker. Вы просили меня назвать клоны, я назвал.
- Окей, если я скажу mesos-container, станет лучше? В целом, там так же есть изоляция и контейнеры. Да, оно большое альтернатива Docker-swarm + Docker, чем самому docker, но контейнеры то там другие.
Или вам нужны именно технологии, которые были до Docker? Тогда есть lxc и chroot.
Тем не менее, Докер — мейнстримовый продукт.
ЗАСЛУЖЕНО.
Стандарт де-факто.
Речь вообще о другом.
Разработчики Докера выбрали инструмент — и не прогадали.
Распространенность, в том числе — и благодаря особенностям языка, который упростил его написание, отладку и портирование.
Огромное количество СЕРЬЕЗНЕЙШИХ продуктов реализовано на golang.
Люди поумнее вас и поумнее меня выбрали его — и НЕ ПРОГАДАЛИ.
А вы тут до сих пор ищете идеальный язык…
Кто-то перешел на Go с Node, кто-то c Python, кто-то с Java.
Об массовых ситуация ОБРАТНОГО перехода — не слуху не духу.
Тем не менее, Докер — мейнстримовый продукт.
Контейнеризация — это мейнстрим. Docker просто самый популярный инструмент, который делать контейнеризацию проще. Но это не делает его разработчиков крутыми, это делает крутым того, кто придумал такую концепцию раньше других. Разницу чувствуете?
Огромное количество СЕРЬЕЗНЕЙШИХ продуктов реализовано на golang.
Огромное количество "СЕРЬЕЗНЕЙШИХ" продуктов реализовано на java, python, c#, javascript. И что? Это как-то исправит недостатки языков?
А вы тут до сих пор ищете идеальный язык…
А Go значит вот идеальный?)
Вопрос в другом: почему вы ожидаете, что Go будет делать то же самое, что и Java? Зачем пихать в Go то, что уже есть в других языках? Тогда это и будет Java, Python, C#. А они УЖЕ есть.
Идеал — недостижим.
Go достаточно развит для серьезного практического использования. Ровно это я и хочу сказать.
На нем УЖЕ и очень ДАВНО пишут серьезнейшие проекты. Крупные конторы. Опытные программисты, которые умнее и вас и меня.
А вы все еще живете в прошлом.
Go достаточно развит для серьезного практического использования. Ровно это я и хочу сказать.
Ну так у него есть недостатки по моему мнению, что мне мешает на них указать?
PHP вот тоже готов для сереьезного практического использования уже лет 10. И что?
Пока ваши претензии выглядят так:
«Я привык иначе» — какой же это довод? Все языки разные.
Что из того, что вы привыкли иначе — то же был другой язык.
Вы не недостатки языка описывайте, а свою невозможность изменить вашу личную привычку — но ваша привычка только ваше личное дело.
Даже то, что авторы считают достоинством, которое они умышленно ввели в язык — строгие правила оформления, которые крайне полезны на больших проектах, — вы трактуете как недостаток.
Это всего лишь ваша привычка. И отсутствие у вас опыта работы на больших проектах. Не более того.
Когда сначала в языке появляется одна бесполезная вещь, которую нельзя отключить (типа импортов), а потом, что бы убедить всех в том, что это нормально, авторы языка разрабатывают тулзу для автоимпорта (у которой проблемы с версионностью как и у всех Golang либ в целом) — это дичь.
Никому не нужен опыт в стрельбе, достаточно только теоретических познаний о нем, что бы понять, что если человек операется на дуло рукой и пинает ногами курок — ничего хорошего не будет.
Я не спорю, Golang отличный язык, который как раз занял важную нишу, но решения в стиле "так надо, потому что так надо", хотя это как минимум сомнительно, все портят.
Особенно смешно то, что никто из тех, кто любит Go не может просто пожать плечами и сказать "Ну хз, захотелось и вплили".
В целом, все так — вам не нравится то, что нравится Пайку — Go не ваш язык :)
http://neverworkintheory.org/2016/04/26/java-exception-handling.html
https://google.github.io/styleguide/cppguide.html#Exceptions
Если вкратце: не все так здорово с исключениями.
Лет 20 назад, когда еще были попытки развить тематику исключений в Java, люди в исключения еще верили. И при попытке отказаться от них тогда — вертели бы пальцами у виска.
Сейчас — люди поумнели и смотрят на мир шире.
Извините, но вы сами читали что по второй ссылке написано? Там написано, что причины в основном исторические. Более того:
On their face, the benefits of using exceptions outweigh the costs, especially in new projects
и
Things would probably be different if we had to do it all over again from scratch.
Удивительно, как люди продолжают ссылаться на Гугл как аргумент против исключений, даже не прочитав, что же там на самом деле написано.
Ну так это же хорошо, все в одном стиле, даже если этот стиль не нравится, то к нему можно просто привыкнуть.
Как противоположность можно привести php, где есть определенная неконсистентность языка.
Пункт 31, последний листинг. Допустим
workerCount := 100
и doit выглядит следующим обоазом
func doit(workerId int, wq <-chan interface{},done <-chan struct{},wg *sync.WaitGroup) {
fmt.Printf("[%v] is running\n",workerId)
defer wg.Done()
for {
select {
case m := <- wq:
time.Sleep(time.Second * 1) // чтобы наверняка задействовать больше одной горутины
fmt.Printf("[%v] m => %v\n",workerId,m)
case <- done:
fmt.Printf("[%v] is done\n",workerId)
return
}
}
Допустим все воркеры запущены, в канал wq посланы все данные и наконец закрыт канал done, т.е. во
всех запущенных горутинах доступны для получения оба канала wq и done. Возможна ли ситуация, когда
все select во все горутинах случайным образом прочтут предсмертное послание из done и закончат свое выполнение? Или я не правильно понимаю логику работы select? Или вообще ничего не понимаю? :)
Как только wq пуст — будет предпринята попытка прочитать из done.
Поскольку done закрыт — будет завершена процедура
Если вы используете done как сигнал о завершении работы — то следует поместить done выше, сделав его самым первым в select
И закрывать done не сразу, а только тогда, когда вам нужно завершить все go-routine с doit
Пока wq не пуст — все go-routine (видимо doit завернут в go-routine? ) будут считывать данные из него.
то что завернут в го-рутину — это очевидно из примера в п.31 статьи. ПОЧЕМУ будут считывать из wq ??? Ведь если у select-у доступны для прима данных несколько каналов, то данные выбираются из одного из них СЛУЧАЙНЫМ образом. Или я все-таки что-то недопонимаю? :)
Если вы используете done как сигнал о завершении работы — то следует поместить done выше, сделав его самым первым в select
а зачем?? чтение при нескольких доступных каналах производится из случайным образом выбранного канала.
или я неправ?
Я постоянно использую подобную методу — создаю фиктивный канал chan struct{}, в который никто никогда не пишет, а использую этот канал для сигнализации, что объект/структура/сервис более не используется — просто вызвав close(done).
Это разблокирует все select и корректно завершает go-routines
Если верхний канал ничего не дает прочитать, то будет произведена попытка чтения из следующего по списку.
Если второй канал ничего не дает прочитать, а default нет, то select останется заблокированным — будут предприниматься попытки прочитать из двух каналов.
После чего нет никакой гарантии какой канал будет прочитан первым.
Но мне все же представляется логичным помещать сигнализирующий о прекращении процесса done — в самый верх. Это на случай начального входа в select, когда мы еще не знаем — сразу же мы из него выйдем или будем заблокированы.
Ведь если процесс уже завершен ДО НАЧАЛА SELECT, то нам НЕ СЛЕДУЕТ ЧИТАТЬ НИЧЕГО ИЗ WQ, а правильным будет сразу выйти по ветке done.
Если у wq будет буффер — тогда поведение недетерминировано и воркеры могут завершиться до выполнения всей работы. В этом случае как-то по-другому нужно написать код.
Для меня самой удивительной особенностью оказалось то, что горутину нельзя взять и принудительно убить.
Вызываю к примеру я в своей горутине какой-то из сторонней библиотеки, которая, например, выполняет бесконечный цикл. Как мне после такого убить свою горутину (к примеру, по таймауту)?
Закладываете внутри вашего цикла конструкцию
for {
select {
case <- stopChan:
default:
}
}
Убиваете методом закрывания канала stopChan или методом записи в него.
пишу вам из 2022 года, тк статья популярна в наше время и ее читают прямо сейчас!
нужно сипользовать контекст context.WithTimeout
, и в горутине в секции select слушать, если получили ctx.Done(), то остановить запрос
50 оттенков Go: ловушки, подводные камни и распространённые ошибки новичков