Go — це не фантастика

Вчора прогулювався по вулиці і натрапив на випуск «Опівночних Балачок» про Golang Madness, про те, як в Go погано. Я люблю пнути Go як і будь-який інший свідомий не-луддит (вибачте, панове грамісти, ви самі обрали своє життя), але... претензії якось такі поверхневі, що я образився за мову.

Чесне слово, fmt — погане скорочення? Ви взагалі C бачили? Чи очікуєте від старих сішників (буквально старих, наймолодшому із лідів проєкта — Робу Пайку — на момент релізу було 55 років), що вони почнуть давати назви на кшталт SingletonBuilderFactory та beginGeneratingDeviceOrientationNotifications? Чи може ти просто любиш Пайтон, який прям «золота середина», за .format(), що не помічаєш import sys? 😁

Короч, більшість претензій рівня «в пайтоні індентація впливає на виконання» або «в ліспах скобка перед назвою функції», дуже поверхнево. Соромно, пацани! І трохи смішно за переживання, що масив — обмеженої довжини. А як інакше, якщо ти хоч бути ефективною не-високорівневою мовою програмування?

Ладно, за згадку про абсолютно тупий підхід до форматування дат — не соромно. Я пам’ятаю в мене був іспанський сором за цю херню ще коли я перший раз з кимось Go обговорював в 2010 році, і нікуди воно не поділося. Замість використати сішну %d.%m.%y або джавну dd.MM.yy, вони вигадали нову неймовірну схему із використанням реальної дати як приклада (Jan 1 03:04:05 2006 GMT+7). Про це можна сказати дві речі: по-перше, використання реальних даних як мови для опису даних — відстій. Помилися в тих даних і напиши там 2024 — і не помітиш, і всюди буде 2024. По-друге, це теж поверхнева проблема, тому що strftime є як ліба і все, забудь про свої проблеми.

От спосіб хендлити помилки нікуди не дівся і він досі абсолютно кончаний. Погано в ньому і те, що if err ≠ nil захламляє код, і те, що він абсолютно неструктурний: errors.New(string) приймає рядок, який потім шо, як в коді визначити, яка це саме помилка? Так, ти сам собі можеш організувати структурні помилки, але в бібліотеках, які ти використовуєш, їх не буде, бо це не системна тема, і знач треба шо, в рядок дивитися? Як гограмісти вирішують як хендлити помилку — я не знаю. В джаві є різні типи в помилок, в кложі кожна помилка — несе структуровані дані, всі інструменти для роботи з цим є. Go? такоє...

Але є більша проблема, а саме — неструктурована конкаренсі. Коли ти відкриваєш новий проєкт, в якому насобачили каналів і обробки цих каналів, а канали передають кудись невідомо куди (найкращий варіант — канал каналів), то знайти, хто тобі прислав ці дані — іноді дуже важко. Авжеж, можна тримати себе в руках і не передавати канали занадто глибоко (або робити очевидним, що ти робиш), але хто це себе в руках буде тримати?

Короч, те що конкаренсі в Go дуже легко робиться — це плюс, на відміну від інших мов — змушує всіх навчитися цим користуватися. Те, як воно зроблене, і те, що нічого ніхто не змінює і не покращує — це мінус. Ви можете спитати, а де краще? В Джаві краще, авжеж, всі ці ThreadPoolExecutor’и — це і є структурна конкаренсі. Писать не дуже зручно, трохи багатословно, але для того і придумали Кложу, щоб JVM було приємніше користуватися.

Висновки які взагалі? Go — прекрасна мова для написання невеликих програм, де не треба особливої бізнес-логіки, бо вона губиться за всіма if err’ами: консольні утіліти там, якісь невеличкі мікросервіси тощо. А для серйозної роботи є Clojure. ☝️

P.S. Обговорення вже є у мене в телеграм-каналі, там ще трохи розкривається тема, тому велкам, читайте/підписуйтеся. :)

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

👍ПодобаєтьсяСподобалось2
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

можно ли найти реальную нишу на фрилансе в голэнг?
или любая цмс на пхп будет профитнее?

Мабуть не для кого не відкрию секрет, що писати лютий гомнокод можна на любій мові програмування.

І це цитата Едгара Дейкстери.

Одже справа як завжди не в мові, а людях.
Але, імхо, на GO я зустрічав менше проектів де хочеться автора тикати пикою у монітор — «хто це зробив? поганий кодер! поганий кодер!» Менше ніж у інших деяких (не буду розводити срач) мовах.
Напевне справа в тому, що Go дуже рідко стає першою мовою і туди переходять зрілі фахівці, які розуміють нащо воно потрібно.
Справедливості кажучи Go не єдина така мова. Туди ж Rust, Clojure, Erlang ...

«хто це зробив? поганий кодер! поганий кодер!»

Да ну типу ніхто не скіпає помилки через плейсхолдер — _ а воно потім вилітає з panic. Супер різниця із std::terminate і не перехопленим ексепшеном в С++. Та же Java коли таке трапляється викине стектрейс з текучого потоку, якщо потоків багато — программа продовжить працювати. Що наприклад при серверній розробці — ізолює обробку різних викликів від різних клієнтів і out of memory — звичаний у випадку занадто навантаженного серверу, від одного клієнта не призвиде до того, що з panic вилетить уся программа з просто усім. Хто такого не бачів — в того не падав Kubernetes кластер. Kubernetes написаний на Go lang.
Go ще одна мова імперетивного програмування, яка не замінює не літнетери не покриття тестами і т.д.

Go ще одна мова імперетивного програмування, яка не замінює не літнетери не покриття тестами і т.д.

Так, звісно.
Я і кажу що справа в людях, а не мові.

Ну що от неможна булоб зробити, щов у класа/структури С був тільки один інстанс А

Як на мене, відміна у тому, що це твоє усвідомлене рішення не обробляти помилку. На відміну від ситуації, коли ти можеш навіть можеш й не очікувати, що там можлива помилка. Плюс ти отримуєш у контекст клас, який описує усі можливі помилки. На відміну від щось неочікуєме прилетіло.

Почав новий проект, go + кубірнети.
Все для мене нове, щось ці кубернети важко заходять.
А от мова Го, після С++ залітає на ура, взагалі усе зрозуміло з 1го разу.

beginGeneratingDeviceOrientationNotifications

Блядь, індусам що це писали новий KPI придумали — замість кількості строк кількість символів?

Це угорській стиль. А ще є угорська нотація — тоді буде записуватись як BGDON. GenericAsynchronousDeviseOrientationNotification — в цій нотації буде GANDON.
Microsoft великі її любителі були колись.
Колись були жарти, що таким чином знайшлось conte.xml та dure.xml

Угорська нотація — це додавання абревіатури типу спереду до назви змінної:
iNumber — тип int
uNumber — тип unsigned
szName — тип string with zero terminating byte
lpszAlsoName — тип long pointer to string with zero terminating byte (long pointer — привіт із 16-бітного x86 світу)

У вікі, до речі, доволі класно розписані і сама нотація, і чому вона «угорська»
en.wikipedia.org/wiki/Hungarian_notation

А тобто LPCSTR і LPWSTR і GANDON, рівно як і conte.xml та dure.xml — з’явились по іншим правилам ?
Я ж кажу приклади з життя.
Там ще купа є приколів з імен і фамілій і інших в міжнародних відносин, які звучать як матерні слова. Що працює в обидві сторони скажімо російські : «как дела» та фамілія Фокін — в англомовних викликає посмішку. Одному колезі якось сказали — що він має fockin amazing last name.

А тобто LPCSTR і LPWSTR і GANDON, рівно як і conte.xml та dure.xml — з’явились по іншим правилам ?

Так, по іншим

LPCSTR і LPWSTR

Абревіатури типів
До речі, Джоел Спольскі ще 19 років тому написав прикольну статтю щодо цих всіх абревіатур — www.joelonsoftware.com/...​ng-wrong-code-look-wrong

GANDON, рівно як і conte.xml та dure.xml

Для кацапських школярів якраз зайде.
Англомовні просто не зрозуміють, у чому гумор із gandon, оскільки це слово у них пишеться не так

Там ще купа є приколів з імен і фамілій і інших в міжнародних відносин, які звучать як матерні слова. Що працює в обидві сторони скажімо російські : «как дела» та фамілія Фокін — в англомовних викликає посмішку. Одному колезі якось сказали — що він має fockin amazing last name.

Відкрий для себе «фальшиві друзі перекладача» — там багато такого і не тільки з іменами
uk.wikipedia.org/...​альшиві_друзі_перекладача

А тобто LPCSTR і LPWSTR і GANDON, рівно як і conte.xml та dure.xml — з’явились по іншим правилам ?

Да, якщо про перші два. (Інші приклади з цих — тільки якщо побачу в реалі, а не в фольклорі.)
Такі скорочення існували задовго до саме «угорської» нотації.

Понял шо все говно, побежал переписывать огромный проект на джаву и clojure

Це все запланована диверсія :))

Відсутність ООП це плюс імо :)

Ні, там є ооп-подібні штуки, але ооп-лайна типу абстрактних фабрик стратегій нема. Часто можна (і треба) писати просто функції.

Я ООП не захищаю. Але :) www.informit.com/...​es/article.aspx?p=1623555 та десь на оф сайті Го теж саме.

Так, на Го ООП не дуже звично запроваджувати, але він відповідає ООП на 100%.

Що викликає питання, так це як там нема абстрактних фабрик та стратегій? :) Звичайно є.

Дивлячись для чого. Для розробки десктопних аплікацій — ООП це дуже великий плюс. Власне для цього і було впроваджено в експлуатацію разом зі Small Talk та GUI, та перекочувало в Macintosh і потім усюди. А Банда 4 яка цим усім займалась, написала книгу — що є безцелером.
Але для дуже великої групи frontend/backend аплікацій набагато більше підходить функціональний подход, реактивне програмування і т.п. Коли ви обробляєте списки та потоки інформації — умовно читаєте та пишите в базу данних (як RDBMS так і NoSQL або якісь SAS сервіси на REST-ах), нахіба вам там треба ООП ? Треба LISP подібні flow обробники які ставляються в потрібні місця. Ті же Spring, Netx.JS і т.п.. ООП треба під капотом фреймверка.
Go lang же це С в стилі JavaScript, умовно мова під розробку Docker та Kubernetes. При чому, там теж почали критичні до перфомансу частини портувати на С, і отримувати до 50% прискорення в цілому github.com/containers/crun

Для GUI идеально подходит конкретно прототипное ООП, с коротинами, и именно поэтому получил распространие Lua в геймдеве и js на браузерах. Go сочетает в себе все возможности для эффективной разработки как серверного кода, так и GUI.

Так а яка різниця між десктопним та веб фронтом в плані (імперативне) ооп чи функціональщина? Що там що там кнопацки клікаються.

А в Web фронті які зараз тренди. TypeScript, Darth та ECMA Script 6 — в які завезли ООП із : інкапсуляцією, поліморфізмом та наслідуванням. Строгу типізацію та перевірку типів, модулі ByteCode — Web ASM, WebGL і тепер вже і WebGPU т.д. по списку. По суті усе підтягують під Java (якраз піонера цього на технології апплетів, які поховали з рештою Apple та Google разом із Flesh / ActionScript — через війни стандартів та HTML5). А це в свою чергу проробки від : С++, Simula 67, Oberon і т.д.
І відповідно фреймверки — типу Bootstrap, Angular, React/Redux, Vue/Nuxt.JS і т.д.
Це мало не повна аналогія з десктопом.

Так реакт це не ооп десктоп. Реакт — це якраз функціональщина.
(Буцтрап — це html/css ви про що)

ну типу просто формошльопити на фрейворках стандартні таски то так може і не треба

а як без фабрики якщо ствоюєте обьект і він потрібен в 40 різних місцях ?

Тут виникне питання, що таке ООП? Оскільки кожна принаймні ширвжиткова мова програмування хотіла пропіаритися підтримкою ООП, то це дуже розпливчато.

Якщо брати кінець 90-х, ще Ґреді Буча, то були три кити: інкапсуляція, поліморфізм та наслідування. Інкапсуляція в Go на рівні пакету, а не класу. Поліморфізм є (через інтерфейси). Наслідування немає.

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

type A struct {
}
type B struct {
  A
}
type C struct {
  A
  B
}
Это абсолютно правильное решение, что инкапсуляция на уровне пакета, поскольку пакет пишется одними и теми же авторами, с одинаковыми правами доступа к исходному коду.

Можливо, але цей підхід трохи нестандарний для ООП, де немає пактів, а є лише класи. Що правильно, а що ні це вже інше питання. Якщо брати Сі, то там також є static для того, щоб інкапсулірувати ім’я в єдиніці трансляції.

Наследование есть, через встраивание

Знову ж таки, по класиці наслідування включає наслідування реалізації, а от його немає. Через вбудову наслідування є навіть у більшості компіляторів Сі:

struct A {
    int x;
};

struct B {
    int y;
};

struct C {
    struct A;
    struct B;
    int z;
};

int main() {
    struct C c;
    c.x = 10;  
    c.y = 20;  
    c.z = 30;  

    printf("x: %d, y: %d, z: %d\n", c.x, c.y, c.z);
    return 0;
}

знову ж, немає ніякої проблеми просто явно вбудувати потрібні класи. Але ми ж не будемо усі мови, що дозволяють визначити структуру у структурі, відносити до ООП? От навіть Сі буде таким чином ООП :-)

Встраивание на Go существенно отличается от встраивания на C, поскольку на Go дочерняя структура наследует все методы, и её можно катить к соответствующим интерфейсам, к которым кастятся родительские структуры. Ближайший аналог на C++ для примера выше на Go это

struct A {
}
struct B: A {
}
struct С: A, B {
}
В отличие от С++, интерфейсы к которым можно кастить дочернюю структуру в Go — никак не декларируются в структуре, что даёт ещё большую гибкость. Так что наследование там есть, с утиной типизацией.
Встраивание на Go существенно отличается от встраивания на C, поскольку на Go дочерняя структура наследует все методы, и её можно катить к соответствующим интерфейсам

Ой, ну додати приведення типів, ... Наслідування з класичного ООП дає можливість перевизначити метод, тобто потребує від компілятора реалізовувати VMT. Усе інше це просто більше зручний синтаксис.

Ближайший аналог на C++ для примера выше на Go это
struct A {
}
struct B: A {
}
struct С: A, B {
}

Може віртуальне наслідування? Бо інакше буде два інстансу struct A. Ну а так просто визначення структури в структурі плюс трохи синтаксичного цукру.

Ці всі віртуальні наслідування то вже костилі, щоб якось мову пофіксити.
Ну що от неможна булоб зробити, щов у класа/структури С був тільки один інстанс А, без усіляких костилів ?

Ну що от неможна булоб зробити, щов у класа/структури С був тільки один інстанс А, без усіляких костилів ?

Так і у Гошечці він не один :)
go.dev/play/p/i0cO53aKHuP

Ну що от неможна булоб зробити, щов у класа/структури С був тільки один інстанс А

Це проблема наслідування ромбу. Якщо брати практику, то інколи нам треба два інстанси A, інколи один. Наприклад, якщо у нас є клас BaseWindow — обгортка над HWND, зверху клас DialogWindows для діалогу та клас TransparentWindow для прозорого вікна, та TransparentDialog зверху. Тут ми хочемо мати один базовий клас, бо нам треба один HWND.

Але проблема у тому, що в цих ситуаціях виникає дуже багато проблем, як створити сумісний доступ до базового класу. Тому в Go буде просто дві структури, і великої відміни від визначенням структури в структурі немає.

Виртуального наследования в Go нет. Утиная типизация даёт более гибкий механизм, который заменяет виртуальное наследование. Достаточно проверить, кастится ли структура к какому-то интерфейсу, или нет. Если кастится допустим к набору методов в интерфейсе TransparentDialog, значит то что надо. Если кастится допустим только к интерфейсу Window, где возвращается дескриптор окна — значит окно в общем случае.
Ещё встраивать можно не объект структуры, а указатель. Этот указатель может при множественном наследовании сылаться на один объект во всех инстансах, и таким образом можно симулировать иногда виртуальное наследование.

Ми не про качиний поліморфізм, ми про наслідування. В Golang є можливість вкладення структури в структуру, але саме наслідування відсутнє. Чи потрібно воно взагалі — питання відкрите.

Чи потрібно воно взагалі — питання відкрите.

Потрібне у тих випадках, коли нормально, що товстий базовий клас має 100500 методів і полів, які треба перевизначати у нащадках тільки малими підмножинами.

GUI, наприклад, краще кладеться на такий варіант, ніж на інші.

І навпаки, я працював з проектами, де не було жодного випадку, де таке мало б сенс, бо там не було такого логіцького наслідування, всі типи незалежні. (Хоча там поруч була мережева серіалізація — може, там воно було потрібне. Не дививсь всередину.)

В отличие от С++, интерфейсы к которым можно кастить дочернюю структуру в Go — никак не декларируются в структуре, что даёт ещё большую гибкость.

И это плохо, потому что даёт возможность передать объект в абсолютно несоответствующее место только потому, что часть полей совпала по названию.

Наследование от интерфейса (типажа) должно быть указано явно.

Ну... в 99% випадків таке співпадіння буде не випадковим. Тому в більшості випадків це просто уникнення boilerplate коду.

У такому випадку треба дозволити такий детект контекстною опцією.

Так, можна додати deriving як у Haskell, але для ООП-мови... Ну чесно, зайва писанина, а от які помилки ми намагаємося виловити? Якщо використовується 1-2 методи, то ми легко проконтролюємо це очима. Якщо десяток, то яка ймовірність, що всі вони співпадуть за сигнатурами?

Виглядає як фіча заради фічі. Спроба привнести у Go щось чужерідне з інших світів. Ком’юніті точно не сприйме це.

Та ні, оця неявність — це херня, теж бісить, насправді. Дивишся на десяток методів, і жодної гадки, які це інтерфейси? Як їх шукать? Такоє.

а якщо інтерфейс десь у залежностях, по всім залежностям грепати?

А в чому проблема? Якщо дійсно є така необхідність, то береш і грепаєш по усьому сирцевому коду ядра. Просто наскільки часто таке виникає?

Гарна спроба через хайп нагнати людей до себе в канал. Візьму собі на замітку :) І головне я 2 рази прочитав і я не зрозумів чи чи це хайт в сторону Go чи ти його похвалив.

Я багато стикався з PHP, JAVA, C#, Python і візсно з JS. І от, останні 10 років застряг в GO. В мене тут на іншому компі зараз є відкритий проєкт. Там Python. Задача проста, зрозуміти як випиляти старий фунціонал. І я відверто скажу, що я скучаю за if...err так як я хотяби розумію яким фровом буде опрацьовані посилки.

Гарна спроба через хайп нагнати людей до себе в канал.

Ну якщо бути чесним — то це мене попросили запостити на ДОУ, не моя ідея. Але не поставити лінку назад — теж якось тупо, так? 😁

Я ще думаю що 10 років дають таку серйозну звичку, що все інше бісить. 😁 Мене так точно шо пайтон, шо го бісять по дуже поверхневим причинам. Імо: дрібниці дратують, але це більше особливості мови, аніж її проблеми.

Погано в ньому і те, що if err ≠ nil захламляє код

Ещё немного об ошибках. Вместо этой конструкции лучше писать вызов функции и проверку в 1 строчке:
if res, err = somefunc(); err != nil {
Далее. Если ошибки — статичные, они просто статично объявляются, типа var ErrSomeBug = errors.New("message") И в дальнейшем проверяются через errors.Is(), errors.As().
Есть ещё простая возможно сабклассить ошибки через fmt.Errorf("message... %w .....", err) с дальнейшей проверкой через errors.Is(err)

як в коді визначити, яка це саме помилка?

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

Авжеж, можна тримати себе в руках і не передавати канали занадто глибоко (або робити очевидним, що ти робиш), але хто це себе в руках буде тримати?

Так это же проблема любого языка, не? Ну типа можно нахеровертить, что угодно без дисциплины.

абсолютно тупий підхід до форматування дат

Это ж тоже нотация всего лишь. Ну мол.. %d, %DD, 01, DAY это же все условная
договоренность. Ну придумали так, ну ок, разве это проблема?

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

Вобще любой язык хорош в нормальных руках и при нормальной дисциплине.

Так, ти сам собі можеш організувати структурні помилки, але в бібліотеках, які ти використовуєш, їх не буде, бо це не системна тема, і знач треба шо, в рядок дивитися? Як гограмісти вирішують як хендлити помилку — я не знаю

В бібліотеках, які Go програмісти використовують, є структурні помилки. Наприклад, навіть в стандартній бібліотеці в пакеті os задекларовано 7 змінних помилок. Деякі функції з пакету os можуть повернути помилку, коли файл не знайдено. Щоб це перевірити, достатньо написати errors.Is(err, os.ErrNotExist).

Кул, ок, я цю історію все-таки пропустив повз очі. Виходить що їх можна свічом по типам оброблять?

Так, можна, з нюансами. В коді мови Go зустрічаються switch для err:

func unpackError(fset *token.FileSet, err error) (token.Position, string) {
	switch err := err.(type) {
	case *scanner.Error:
		return err.Pos, err.Msg
	case Error:
		return fset.Position(err.Pos), err.Msg
	}
	panic("unreachable")
}

Але switch не працює з wrapped помилками. Тому приходиться все одно використовувати errors.Is, як тут:

err = os.Symlink("target", filepath.Join(tmpdir, "symlink"))
switch {
case err == nil:
	return true, ""
case errors.Is(err, syscall.EWINDOWS):
	return false, ": symlinks are not supported on your version of Windows"
case errors.Is(err, syscall.ERROR_PRIVILEGE_NOT_HELD):
	return false, ": you don't have enough privileges to create symlinks"
}

Ну все одно терпимо, краще, аніж було раніше.

А насправді це костиль, який виник через відмову від механізму ексепшенів. Подивіться на код — обробка ситуації в якій поточна версія операційної системи не підтримує сумлінки, по суті не можлива.

Чого не можлива? Нове значення додати та й усе.

Куди ? Сумлінки не підтримуються, тобто Windows XP і старше — бо підтримку сумлінків додали в Windows Vista та Server 2008. Або недостатнью привілієв задля створення. І через брак механізму ексепшенів — треба додавати додатковий код обробки помилок, на кожний такий виклик, який по суті є зайвим. Крім того — його банально можна забути додати і отримати взагалі undefined behavior в деяких випадках. Тоді як есепшн зробить fail fast, я у разі механізмів checked exception як в Java програмісту доведеться обробити таку ситуацію інакше код не компілюватиметься.
Це великі мінуси мови, пов’язані виключно з вимогами Google до критичого софта серверної інфраструктури.
google.github.io/...​/cppguide.html#Exceptions та google.github.io/...​e_Type_Information__RTTI
При цьому як не дивно залишили Mark-Sweep Garbage Collection — tip.golang.org/doc/gc-guide. Wе десь рівень Java 1.6 (2007 рік) — тоді як сучасна Java 23 це або G1 або Z collector docs.oracle.com/...​/java/javase/23/gctuning
Ну тобто підхід спірний, дуже спірний. На загал для серверної інфратсруктури напевно так робти вірно, але для скажімо десктопного софту і т.д. ?

Ну додати обробку, обгорнути та повернути вашу нову помилку як мінімум для цього юзкейса. Це можливо й проблема, але це едж кейс.

Ексепшни — це зло. Вони додають additional control flow та не гарантують банально нічого. Помилка — це значення, для його обробки не потрібен зайвий механізм. Це ніяк не стосується вимог Google. Вимоги гугла лише приймають цей факт.

btw: github.com/...​c/os/file_windows.go#L289 взагалі-то не поганий код.

Ексепшни — це зло. Вони додають additional control flow та не гарантують банально нічого.

Це не так, сама ідея з’явилась в мові PL/I. В ній 3 доволі розумні концепції — перша це розділяти код обробки помилок від коду логіки. Друга обробка помилок на різних рівнях вкладенності ви не можете зробити глобальний try {} catch в main ні в С без setjmp()/longjmp() unwind ні в Go. Третя групування типів помилок, зокрема за дпомогою ООП.
В дійсності ці норми обробки помилок, це наслідок невдосконалого мехінізму
setjmp()/longjmp()
Які з резштою замінили на libunwind та EHsc.

btw: github.com/...​c/os/file_windows.go#L289 взагалі-то не поганий код.

Насправді він таке собі, ще можна читати — але вже треба дебагер раптом, що.
От те саме на Modern С++ (C++ 17+)
en.cppreference.com/...​filesystem/create_symlink

При цьому як не дивно залишили Mark-Sweep Garbage Collection — tip.golang.org/doc/gc-guide. Wе десь рівень Java 1.6 (2007 рік) — тоді як сучасна Java 23 це або G1 або Z collector docs.oracle.com/...​/java/javase/23/gctuning

Вы явно по-разному понимаете mark&sweep с авторами этой доки. У вас он превращается чуть ли не в stop-world. В Go сборщик инкрементальный, и максимально мелкими шажками, сколько разумно — они это считают критичным.

У алгоритма єсть существенная проблема — фрагментация памяти. Это была моей основной головной болью до Java 1.7 как мимнимум лет 5, когда JBoss, WebSphere и WebLogic постоянно ложились с Out of memory и нужно было постоянно профилитровать и тюнить GC.
PDF по GC был распечатан и стал настольным.
G1 снял проблему одномоментно. У Go и D — до сих пор этот алгоритм. Собственно crun и показывает поэтому в половину большую производительность от runc, при идентичном алгоритме портированом с Go на С. Реальная разница — сборка мусора, и более оптимизирующий компилятор.

о, чергова тема про те, яка Go погана, від людей, які не написали на ній більш ніж майже нічого))))
1.

if err ≠ nil

дозволяє не городити

try {} catch{} catch{} catch{} ...... catch{} finally{}

2.

Так, ти сам собі можеш організувати структурні помилки, але в бібліотеках, які ти використовуєш, їх не буде, бо це не системна тема, і знач треба шо, в рядок дивитися? Як гограмісти вирішують як хендлити помилку — я не знаю

пан не зміг сходити трошки далі, ніж перша лінка в гуглі чи один файл в рандомному репо?)
тоді я допоможу, еррор хендлінг серед найпопулярніших репозиторії по Go:
— gin — github.com/...​/master/errors.go#L18-L30
— k8s — github.com/...​kubelet/errors.go#L23-L28
— docker compose — github.com/...​ain/pkg/api/errors.go#L29
— go-ethereum github.com/...​orm/blob/master/errors.go
і це 5хв гугління.
те, що ви не зустрічали як це обробляється, то не означає, що так не роблять

3.

В Джаві краще, авжеж, всі ці ThreadPoolExecutor’

це і є гірше, бо треба городити обʼєкти, передавати один в інший, реалізовувати методи інтерфейсів і тд — занадто багато бойлерплейту

4.

А для серйозної роботи є Clojure. ☝️

вишенька на торті)
це та Clojure, якої нема в зарплатному опитуванні від ДОУ, бо там навіть десяток анкет не назбиралось?)))
dou.ua/...​-report-devs-summer-2024

від людей, які не написали на ній більш ніж майже нічого

Звідки дровішки? 😁

це і є гірше, бо треба городити обʼєкти, передавати один в інший, реалізовувати методи інтерфейсів і тд — занадто багато бойлерплейту

То напиши собі хелпер, щоб прибрать бойлерплейт. І взагалі, коли це бойлерплейт лякав програміста на Го?

це та Clojure, якої нема в зарплатному опитуванні від ДОУ

Ага, це та, в якої найвищі зарплати в опитуванні Stack Overflow.

Я не розумію, нахіба ти понти кидаєш? Я вказав на речі, які мене харять, якщо у тебе є думка, що насправді все добре — візьми і опиши, як все добре, не треба руками розмахувати, це противно.

зарплати найвищі, бо писати ніхто не хоче. так само як і Nim

Ви ж відкрили тему порівняння Go та Clojure, наче знаєте щось про Go з практичного досвіду

Якщо це так, то покажіть, що саме краще в Clojure у порівнянні з Go

Вам же на вашу критику, що на Go пишуть тільки маленькі мікросервіси й маленькі програми, показали Kubernetes, який створений на Go

Блін, Ярослав, нахера переход на особистості? Я дохера знаю про Го з практичного досвіду, і писав на ньому ще тоді, коли ти в універі навчався (і не тільки тоді), так я ж не пишу під кожним коментом «діти, заспокойтеся»? Бо заспокойтеся, йо-майо, не треба кожну критику сприймати як персональну атаку.

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

Імхо Кубернет хороший приклад. Нереально дохера коду і для того щоб їм користуватися треба спеціальні виділені експерти. Всі — молодці.

Ви перші дозволили собі таку поведінку, я ж далі ввічливо спілкуюсь

Вам варто перечитати свій стиль написання, мій стиль написання й стиль Романа, порівняти та зробити висновки

🙄 написання «ви» замість «ти» не робить розмову ввічливою.

Ввічливою розмову робить обговорення ідеї, а не людей. Коли він пише «від людей які нічо не шарять», «пан не зміг», або ти пишеш «наче знаєте шось» — це неввічливість.

Коли я пишу «в го оце дуже погано» — це нормально, бо це думка не про тебе, не про Романа, не про Роба Пайка і ні про кого іншого, а про те, що є щось, що мене не влаштовує. Чи треба з цим щось робити — авжеж ні, я взагалі ніяких екшенів ні від кого не очікую.

Нашо я написав цю статтю — написано на самому початку статті. Ладно, тре мені чимось кориснішим зайнятися, аніж людей навчати сперечатися.

Ви могли додати контекст й описати свій досвід з Go, якщо вже почали критикувати

Міг би, але б це зайняло ще більше часу — а я й так його витратив достатньо.

І взагалі, автор розраховує на здоровий глузд і буденне милосердя читачів.

У кожної спільноти є свої особливості, етнічна складова. Автору варто їх враховувати, як і те, що знання про спільноту можуть застарівати, оскільки спільнота змінюється.

Якщо автор розраховує на милосердя читачів, то ймовірно на LinkedIn.

Враховувати токсичність я єбав, якщо чесно.

У вас хибне сприйняття спільноти DOU

Коли ви називаєте спільноту токсичною, то ставите себе в один ряд із тими, хто раніше також називав цю спільноту токсичною:

Привіт, вже дуже звична ситуація коли на DOU реєструються різноманітні коучі, створюють теми про успішний успіх або ще якусь маячню, отримують вагон критики від спільноти, ображаються та звинувачують спільноту у токсичності.

Хибне сприйняття чи ви з Романом доєбалися чи є в мене право критикувати мову?

Чи ставлю я себе з кимось в один ряд тим, що використав такий самий термін? Сумніваюся.

Я спілкувався з вами ввічливо
Роман також спілкувався з вами ввічливо

Критика краща за ігнорування, особливо якщо ви хочете, щоб на ваш телеграм-канал підписалися

В мене відсутня можливість змінити ваше сприйняття, що ми до вас докулупались

знаю про Го з практичного досвіду, і писав на ньому ще тоді, коли ти в універі навчався

Я навчався в університеті з 2009 по 2013 рік, мова Go була створена в 2009 році, просто щоб доповнити картину

Мова розвивається, про це є навіть тема на DOU за 2024 рік: «Еволюція в Go: огляд атавізмів»

Я навчався в університеті з 2009 по 2013 рік, мова Go була створена в 2009 році, просто щоб доповнити картину

Перший код на Го я написав в листопаді 2010.

І взагалі, коли це бойлерплейт лякав програміста на Го?

особливо тішить чути це від людини, яка приводила в приклад Джаву))))))

Ага, це та, в якої найвищі зарплати в опитуванні Stack Overflow.

якщо на Го буде писати 100 людей і з середньою зп 5к, а на Кложі 2 людини з середньою зп 6к, то я б сильно не тішився тим, щоб писати на Кложі.
треба в цих людей запитати скільки часу приходиться на пошук роботи на таких єдинорогових технологіях

Я не розумію, нахіба ти понти кидаєш? Я вказав на речі, які мене харять, якщо у тебе є думка, що насправді все добре — візьми і опиши, як все добре, не треба руками розмахувати, це противно.

та які понти, не дай боже
ніхто не розмахує, я дав список репо, де є еррор хендлінг, а от хто розмахував руками зі словами «як визначити помилку, хіба що йти дивитись в стрінгу» — риторичне питання

та які понти, не дай боже
о, чергова тема про те, яка Go погана, від людей, які не написали на ній більш ніж майже нічого))))
пан не зміг сходити трошки далі
вишенька на торті)

І дійсно, які понти...

А для серйозної роботи є Clojure

Хотів зробити список компаній, які розробляють на Clojure, але там немає бажаючих

А мож ще це, там список компаній які розробляють на OCaml. Правда там будуть в основному французські корпи :)

Висновки які взагалі? Go — прекрасна мова для написання невеликих програм, де не треба особливої бізнес-логіки, бо вона губиться за всіма if err’ами: консольні утіліти там, якісь невеличкі мікросервіси тощо.

То ми нарешті вас знайшли

Це про вас на Reddit пишуть:

I was told by a guy who is the Director of Engineering at a big streaming service (not netflix), that Go is only good for creating routers and middlewares. Any other backend service written in Go is bad. I dont agree, but what do you think about this?

Не про мене, але хтось очевидно не луддит. 😁

Підписатись на коментарі