LINUX.ORG.RU

Почему Go это плохо, и он вам, на самом деле, не нужен.

 ,


7

15

Давайте я вам поясню про язык Go, откуда у него растут корни, и почему его на самом деле не стоит использовать. То что напишу ниже, это взято как из инсайдерской информации, так и из материалов, доступных в интернетах.

Дело в том, что Go это, на самом деле, «решение» внутренних гугловских проблем. Но отнюдь не проблем горизонтального масштабирования серверного ПО, как многие почему-то думают. Он приспособлен специально для использования в гугле вот в каком контексте.

Гугл нанимает большое количество тупых студентов, только-только после вуза или ПТУ, и заставлять их писать хоть какой-то простой код. И делать минимум ошибок, при этом. Для этого Go сделан таким тупым и упрощенным. И выкинут в паблик он только для того, чтобы вероятность, что у такого студента, только пришедшего в гугл, было хоть какое-то знание Go, была выше нуля.

Но дело вот в чем. В гугле, на самом деле, над каждой командой гошников стоит тимлид, или целая группа, который/которая вот этим взаимозаменяемым роботам-гошникам расписывает всю систему, чуть ли не вплоть до состояния конечного автомата, до if-ов, и показывает куда и что писать. Поэтому же Go на корню режет всю креативность, поэтому там нет практически никаких средств абстракции, и поэтому он не дает делать вообще ничего сложного. Дабы программисты на нем вообще ничего лишнего не думали, а кодировали все чуть ли не побуквенно по указаниям умных людей.

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

Тут возникает вопрос - а почему этому тимлиду не дать в руки кодогенератор, вместо всей этой accidental complexity, возникающей из-за огромного количества строк кода, и из-за затрат на коммуникацию?

А тут надо понимать, как внутри устроены огромные корпорации типа гугла.

Их давно пожрал рак бюрократии. Там у менеджерских и околоменеджерских должностей один из главных критериев промоушнов, или вообще даже ассесмента(усидения на должности), это количество людей у тебя в подчинении. И количество говнокода в вакууме которая твоя команда написала. И вот все эти люди, сидящие на более-менее средне-высоких должностях, постоянно бодаются за эти промоушны и ассесменты. Это их главная и единственная цель. Поэтому, ни о какой эффективности тут речи не идет вообще от слова совсем. Тут главное - корпоративные игры, количество голов в твоем стаде и количество и размер высеров, которые это твое стадо произвело(причем буквально, важны SLOC).

Естественно, это все отражается на качестве продуктов, и это видно как по полному прекращению инноваций в гугле, так и по постоянно мелькающим и закрывающимся высерам этой компании - hangouts, duo, google plus, google wave, и прочее и прочее, можете еще вспомнить много чего.

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

Никакой мифической простоты в отладке и в понимании кода Go не приносит. Да и сложность программных систем растет совершенно не из-за понятности/непонятности какой-то отдельной взятой строчки кода или функции. Потому, что, во-первых, понятность это понятие субъективное, во-вторых потому, что, отдельно взятая фунцкия на 5 строк понятна любому опытному программисту, будь она написана хоть на Rust, хоть на Common Lisp.

Сложность программных систем возникает из-за их размера. И Go эту проблему значительно ухудшает. Человек не может удерживать в голове слишком много вещей, даже если каждая отдельная вещь - очень простая. Количество RAM в голове ограничено.

В случае если вы не хотите выкидывать кучу денег просто так, и скорее предпочли бы нанять немного, но более-менее опытных программистов, Go будет только вреден, потому что все вменяемые люди от него, на самом деле, плюются. Он реально отталкивает опытных людей, которые способны понять сложные требования и написать, и поддерживать, более-менее сложные системы уровнем хотя бы нескольких сервисов плюс БД и MQ.

★★
Ответ на: комментарий от alysnix

Я вообще-то не об этом хотел поговорить. Просто сказал, что существует достаточно устойчивое мнение среди пользователей IDE, что если IDE не может в полноценный автокомплит и автоматизированный рефакторинг, то это уже и не IDE по современным меркам. В случае с C++ достижение этого автокомплита и рефакторинга местами в принципе невозможно из-за особенностей самого языка. Отсюда и утверждение о том, что полноценные IDE для C++ недостижимы.

Данная точка зрения мне понятна. Но, т.к. я не пользуюсь IDE, то наличие отсутствие «полноценных» IDE для какого-го либо языка для меня вообще не проблема.

Хотя вот Java оказался таким языком, в котором без IDE писать сложно.

eao197 ★★★★★
()
Ответ на: комментарий от alysnix

Если понятия IDE в строгом виде нет, то конечно можно объявить её существующей, назвав, допустим, морковку IDE.

Если же смотреть по конкурентам, то в понятие IDE входят, по убыванию критичности:

  • возможность перейти к определению сущности
  • возможность найти все ссылки на сущности
  • автокомплит
  • рефакторинг

Первое наиболее критично, и даже его в С++ сделать нельзя. Так же и про проекты, если сделать вид, что понятия проекта нет, то можно табуретку назвать проектом. Если же смотреть по конкурентам, то понятие проекта как раз и позволяет создать то, что у конкурентов называется IDE.

den73 ★★★★★
()
Ответ на: комментарий от alysnix

Хорошая оговорка, «насколько я НЕ знаю». Честность - это хорошо.

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от eao197

Просто все давно экскаватором копают, а ты всё ещё лопатой. Конечно, ты более детально знакомишься с грунтом и даже, наверное, лучше его понимаешь, чем экскаваторщик. Можешь выкопать очень маленькую ямку, меньше ковша экскаватора. Но если ты копаешь ради денег, то экскаваторщик больше заработает (если, конечно, на ремонт экскаватора всё не потратит).

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от den73

возможность перейти к определению сущности

это есть, и железно. если автокомплит делается компилятором, как в clang(как собствнено и должен делать настоящий автокомплит, а не левыми парсерами), то компилятор не может компилировать использование символа, если не знает его определения. то есть или это будет ошибка компиляции, или компилятор вам даст файл и строку где данный символ определен.

возможность найти все ссылки на сущности

без проекта это не сделать, но если IDE имеет понятие о линкуемых файлах, то это можно найти.

автокомплит

см п 1. автокомплит от компилятора не сработает на шаблонах, если тип никак не оговаривается. если тип обьекта известен - то автокомплит будет всегда и настоящий.

рефакторинг

смотря что под ним подразумевать.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 2)
Ответ на: комментарий от den73

минимальные средства абстракции в лице интерфейсов есть, а ООП в стиле C++/Java всё равно сильно неудачное, поэтому избавление от него может считаться выигрышем

Классы в Python добавили для учебной программы.
Для практического применения в Python они не нужны.

tp_for_my_bunghole
()
Ответ на: комментарий от tp_for_my_bunghole

Я вот 10 минут назад читал документацию по Lark, и обойти дерево можно, только переопределяя методы в наследниках, с помощью визитора. Это штатный метод, пришлось писать костыль, чтобы не возиться с этим. Так что не могу согласиться, что классы не нужны. Unittest - тоже класс, хочешь писать юниттест - определяй свой класс. Возможно, есть другие библиотеки, без классов, но мне ChatGPT именно эту посоветовал, и судя по названию, она модная библиотечка, может быть даже эталонная.

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от alysnix

автокомплит компилятором реализуется тривиально. компилятор должен проделать синтаксический анализ до точки в тексте где начинается дополнямый символ. и дать интерфейс для вытаскивания всех видимых в данной точке символов. после чего вытаскиваются все символы, подходящие по началу дополняемого символа, к ним добавляются зарезервированные слова, подходящие по началу, и суются в список. список показывается в окне, которое и есть окно автокомплита.

и такой автокомплит никогда не ошибается

alysnix ★★★
()
Ответ на: комментарий от alysnix

Да, для данной конкретной компиляции, а программа на Си(++) - это бесконечное семейство программ, определяемое конфигурацией и ключами -D в командной строке. Я сразу же это оговорил, см. выше.

Поэтому да, для конкретной конфигурации можно создать IDE для С++, но переход к определению и все остальные операции будут верны только для этой конфигурации. Именно для этого существует compile_commands.json. В Го не так. Хотя, если честно, наверное и в Го такая ситуация возможна. Просто в Го надо постараться, чтобы её сделать, а в С/++ она всегда имеет место.

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 3)
Ответ на: комментарий от den73

Для практического применения в Python классы не нужны когда есть duck typing. Но если уже внедрили классы то находят применение.

После обучения на Python будет трудно начать Go потому что там композиция вместо наследования. «Но говорили жыж что это простой язык?». Язык простой, на замену C++.

tp_for_my_bunghole
()
Ответ на: комментарий от tp_for_my_bunghole

Согласен, что они по сути в языке были бы не нужны, и, вероятно, было бы лучше без них. Но теперь их сделали, впихнули в библиотеки и они стали нужны.

den73 ★★★★★
()
Ответ на: комментарий от den73

Именно для этого существует compile_commands.json.

и правильно существует. это формальное описание всяких ключиков и дефайнов (это небось вижуал студия какая), чтобы ide знала ваши намерения. по ним строится командный файл для сборщика и все собирается. а также дефайны оттуда подсовываются компилятору, при заказе парсинга для автокомплита.

alysnix ★★★
()
Ответ на: комментарий от alysnix

Так я и сказал, для одной конфигурации это сработает, но конфигурация не одна.

den73 ★★★★★
()
Ответ на: комментарий от den73

Но ведь они же неодинаковы. Во втором случае у вас вложенные окружения, сразу понятно, что *print-base* находится в контексте with-open-file, а в первом — просто плоский список утверждений. Где заканчивается область видимости для (let a 1)? Кроме того, я всё ещё не понимаю проблемы. Даже для меня, чьё знакомство с лиспом ограничивается конфигом emacs’а и прочтёнными SICP и PCL не составляет ни малейшего труда понять этот код. Ну, заменили (let ((x y)) <code>) на (let x y) <code>. Компилятору стало сложнее, а мне легче не стало (потому как изначально трудно не было). Так и смысл менять шило на мыло?

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

Так и смысл менять шило на мыло?

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

так достигается процветание.

alysnix ★★★
()
Ответ на: комментарий от ugoday

S-expr там для всего. это универсальный способ записи некоей семантики. с которой потом можно работать так и сяк.

alysnix ★★★
()
Ответ на: комментарий от ugoday

S-expressions составляют дерево. Любой компилятор трансформирует синтаксис в дерево, называется Concrete Syntax Tree которое преобразовывает в Abstract Syntax Tree. Иногда сразу AST как в Go.

Исключение Pascal-based языки где всё упрощено за счёт своего синтаксиса.

tp_for_my_bunghole
()

Из новых наблюдений за сусликами: Го поощряет своевременную обработку ошибок; не позволяет забивать на неё до лучших времён, как языки с исключениями. Это хорошо.

Nervous ★★★★★
()
Ответ на: комментарий от ugoday

Есть такое местами. Но если большинство функций возвращают err вторым значением, то зачастую можно просто возвращать один вызов такой функции вместо двух значений и сваливать разбор ошибок на какого-нибудь бедолагу выше по стеку вызовов %)

Щас набежит отряд лисперов с рестартами наперевес, ждём.

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от Nervous

В смысле, если я написал:

(err, x) = ЗасуньНогуЗаУхо()
if err {
  return err
}

То это значит, что я своевременно обработал ошибку (простите, если синтаксис напутал)?

den73 ★★★★★
()
Ответ на: комментарий от Nervous

Не с рестартами, а с invoke-debugger по умолчанию, что является всегда включённой JIT-отладкой. Начала машина падать с моста, к примеру - и тут же прилетает добрый ангел и держит её на руках, пока люди не подоспеют и не спасут. А спасти можно, поскольку сюжет не отлит в гранит, а допускает вмешательство в любой точке. Не рестарты, а restart frame в дебаггере, что не является свойством языка, а является свойством хороших рантаймов. Но вам-то куда это понять?

den73 ★★★★★
()
Ответ на: комментарий от ugoday

Они одинаковы, я нарисовал результат макрорасширения первой формы. Область видимости любой конструкции идёт до закрывающей скобки охватывающей «перги», как и во всех обычных языках типа Го. Раз в обычных языках это не вызывает затруднений, то и тут не должно. Если надо, чтобы область видимости закрывалась раньше, можно сделать «перги» вложенными или написать эту конструкцию в полной форме.

den73 ★★★★★
()
Ответ на: комментарий от ugoday

Это количественная проблема, которая проявляется, когда читаешь или пишешь код в большом объеме. Количество скобок в перге уменьшается раза в полтора, вложенность - раза в два-три. Т.е. это существенно облегчает синтаксис лиспа, и намного сокращает заборы из закрывающих скобок. Но если тебе не надо, то и не пользуйся. В общем-то уже никто и не пользуется, т.к. я на лиспе почти ничего не делаю последние несколько лет.

den73 ★★★★★
()
Ответ на: комментарий от den73

То это значит, что я своевременно обработал ошибку (простите, если синтаксис напутал)?

По крайней мере, она у тебя не упадёт на пол и не уронит всё приложение, как это бывает с необработанными исключениями. Особенно актуально, если ошибка происходит редко.

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от den73

Оно плавно опустится на пол

Если функция возвращает ошибку, а ты её не принял/обработал, компилятор тебя завернёт. Натурально, там даже неиспользуемая переменная — это ошибка компиляции.

Ошибка, Карл! Только так можно заставить приматов делать как положено %)

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от den73

можно сделать «перги» вложенными

Threading macros изобретаешь? %) А что здесь значит «перга»? Это же пыльца вроде так называется.

Nervous ★★★★★
()
Ответ на: комментарий от Nervous

Да я умею на Го писать, вот же мой проект:

https://tvoygit.ru/budden/semdict

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

Да и вообще уважаю этот язык.

den73 ★★★★★
()
Ответ на: комментарий от Nervous

Я ничего не изобретаю, уже давно изобрёл, внедрил, пользовался массово, вот, например. Это хоббийный код, но был и ради зарплаты написанный (мне почти жаль тех, кто получил его в наследство):

https://tvoygit.ru/budden/jar/src/branch/master/ит/ооп/у-м/упаковка-методов.lisp#L62

Но не знал, что это так называется. Откуда это название?

Да, это она. Первая версия называлась proga, но вышла не совсем удачной. Шаблон prog? закончился, и поэтому пришлось придумать другое слово. Перга в том смысле, что полезна для здоровья разработчика (для моего, во всяком случае). Так-то вообще перга - это «пчелиный хлеб», которым они кормят своих пчелят. А люди его отбирают и сами едят. Весьма рекомендую, куча витаминов, содержит прополис и на вкус кисленькая, а не приторная, в отличие от мёда. Правда и денег стоит.

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 4)
Ответ на: комментарий от Nervous

Посмотрел и я на Go. Прикольный язык. Любая программа - это километры простого кода где в все явно и в принципе не может быть каких-то фокусов. Идеальный вариант для того чтобы писать что-то более-менее сложное относительно большой коммандой в которой постоянно происходит ротация людей.В отличие от всяких «выразительных» языков не нужно держать в голове кучу деталей, ньюансов и контекстов языка, а можно сфокусироваться на решаемой задаче.

Но так как писать такой код многим программерам становится скучно - скорее всего язык будут «развивать», т.е. усложнять. Либо делать какой-нибудь убер-фреймворк. Тут в качестве аналогии можно привести Java, которая сама по себе простая и понятная, и Spring - в котором куча деталей, ньюансов, кодогенерации и т.д. Надо держать в голове все это для того чтобы понять как приложение будет работать в определенном окружении.

И при этом если Spring - более-менее стандарт и работает одинаково для всех, то в лиспах каждый сам себе хозяин. Каждый раз разбираться в том «что имел ввиду автор» - это адъ.

Elidee
()

Но дело вот в чем. В гугле, на самом деле, над каждой командой гошников стоит тимлид, или целая группа, который/которая вот этим взаимозаменяемым роботам-гошникам расписывает всю систему, чуть ли не вплоть до состояния конечного автомата, до if-ов, и показывает куда и что писать. Поэтому же Go на корню режет всю креативность, поэтому там нет практически никаких средств абстракции, и поэтому он не дает делать вообще ничего сложного. Дабы программисты на нем вообще ничего лишнего не думали, а кодировали все чуть ли не побуквенно по указаниям умных людей.

Да это же план Даллеса от мира ПО.

во-вторых потому, что, отдельно взятая фунцкия на 5 строк понятна любому опытному программисту, будь она написана хоть на Rust, хоть на Common Lisp

Очень интересное заявление. Уважаемый погромист, пойми мне, что в этой строчке на J написано? r=. (":5{.6!:0''),LF,(;2{old),LF,(;1{old),LF,;1{new

Aswed ★★★★★
()
Ответ на: комментарий от Virtuos86

При всех недостатках го, это сейчас единсвенный ЯП(по крайней мере из популярных), в котором асинхронный код пишется без async/await и каких-то доп абстракций. Прост потому что все стандартные операции ввода вывода асинхронны. Еще он быстро компилируется в производительный код и кросскомпиляция тож оч простая. Эти свойства делают его удобным для написания НЕБОЛЬШИХ серверов. А сейчас как раз популярны микросервисы

Aswed ★★★★★
()
Ответ на: комментарий от lovesan

Как здорово, что ты один прекрасно понимаешь не только как работает IT индустрия, но и нормальную инженерию. Еще и великий заговор гугла собственноручно раскрыл. Золотой ты человек. Не забывай ток пить таблетки

Aswed ★★★★★
()
Ответ на: комментарий от Elidee

в лиспах каждый сам себе хозяин

Не знаю, как там в других лиспах, а в кложе вполне себе есть общепринятые решения типичных задач (обычно это библиотеки, а не фреймворки). Должны и в лиспах быть — просто, наверное, типичные задачи там другие, не штамповка одинаковых сервисов как на конвейере.

С другой стороны, поискал я dependency injection на Го (аналог жабного Spring/кложевого Integrant) и нашёл аж целую охапку. Так что не так всё однозначно (тм) %)

Nervous ★★★★★
()
Ответ на: комментарий от den73

Перга в том смысле, что полезна для здоровья разработчика

Надеюсь, коллеги, которым приходится разбирать код с различными «пергами», думают так же. И ещё надеюсь, что они не знают, где ты живёшь.

Nervous ★★★★★
()
Ответ на: комментарий от Nervous

Лисперы, которые не умеют прятать следы, уходя из проекта, не выживают. Так называемый естественный отбор лисперов ☺️.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Aswed

Не забывай ток пить таблетки

Если он не забудет выпить таблетки, то таких срачей на LOR-е не будет :(

eao197 ★★★★★
()
Ответ на: комментарий от Nervous

Не знаю, как там в других лиспах, а в кложе вполне себе есть общепринятые решения типичных задач (обычно это библиотеки, а не фреймворки)

Да, но в Go

for i, v := range aslice {
  //do something with i and v
}

всегда делает одно и тоже, а вот в Clojure

(do-something-with a-list an-action)

в каждом проекте свой и что он делает зависит только от психического здоровья членов команды.

и да, я в курсе про map, но иногда «map не хватает»

Elidee
()
Ответ на: комментарий от Elidee

Но так как писать такой код многим программерам становится скучно

Скучным может быть не язык, а задача. Если задача сложная и интересная, то язык вобще куда-то на третий план уходит. Профи задачу решит на любом языке (непрофи ноют про расчудесные лишпы). Сейчас на гошке в одной РФ есть уже несколько кантор, пилящих с нуля бигдата платформу, или уже запиливших. Так что с задачами тут все в порядке.

slew
()
Ответ на: комментарий от Elidee

в Clojure (do-something-with a-list an-action) в каждом проекте свой

В кложе встроенные конструкции типа

(loop [x ... y ...] 
   ;; do something with x and y
   )

тоже всегда делают одно и то же, а пользовательские функции в Го тоже в каждом проекте свои. В чём принципиальная разница?

Nervous ★★★★★
()
Ответ на: комментарий от Nervous

Дополню пример. Для Go

for i, v := range aslice {
  AnAction(i, v)
}

чтобы понять что происходит, нам нужно сходить в функцию AnAction

в Clojure

(do-something-with a-list an-action)

чтобы понять что происходит надо сходить и в an-action и в do-something-with, который может оказаться макро применяющим an-action к элементам массива с индексами-числами Фибоначчи, причем к первому элементу применяется дважды.

и так как я в Clojure не силен - можно ли определить свое макро или функцию с именем loop и заменить стандартную реализацию своей?

Elidee
()
Последнее исправление: Elidee (всего исправлений: 1)
Ответ на: комментарий от Elidee

может оказаться макро

Это да. Думаю, именно поэтому первое правило клуба писателей макросов — не писать макросов, если можно обойтись функцией. Если уж совсем невмоготу, говорящие имена типа def<something> или with-<something> помогают, и отличающаяся подсветка синтаксиса для макросов/специальных форм помогает тоже .

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ограничение на отправку комментариев: