Golang

Материал из Неолурк, народный Lurkmore
Перейти к навигации Перейти к поиску

Go aka Golang — язык программирования, разработанный Google в очередной попытке создать идеальный™ компилируемый структурно-ориентированный язык программирования с многопоточностью и интерфейсами. Вобрал в себя особенности синтаксиса C, Pascal и немного Python. Доставляет тем, что выглядит и ощущается как интерпретируемый язык, но по факту — компилируемый, да и к тому же имеет строгую статическую типизацию.

Это не какашка, с торчащими из неё глистами и глазами, и даже не суслик, а маскот Го.

История[править]

В незапамятные времена был Bell Labs, с которым как-то приключилась острая анальная боль по причине того, что разрабы из Bell Labs использовали дорогущее железо для игры в игрушки. Пистонов им навтыкали, в качестве побочного эффекта которых родилось два мема: Unix и C. Unix и C со временем превратились в религию, и патриархами её были Кен Томпсон, Деннис Ритчи, ещё какие-то люди и Роб Пайк. Для нашей истории нам будут интересны первый и последний, а пока они неинтересны надо отметить, что эта парочка отличилась не только тем, что они были в той группе, которой Bell Labs пистонов навтыкала за игроманство на рабочем месте, но и другими деяниями, типа изобретения utf8 и супер-Unix, aka Plan9. Роб при этом успел отличиться на поприще погромистской литературы, а Кен сорвать куш Turing Award.

Благодаря успеху Unix им удалось застолбить для UnixWay нишу среди других религий, и позиционировать себя патриархами этой религии. Помимо них есть и другие, пророки, типа Ричарда Столлмана или Эрика Раймонда, но они примазались после, и достичь сходных результатов им не удалось. Столлману удалось запилить GNU, но Gnu is Not Unix, и поэтому недотягивает… Но я отвлёкся. Так вот, вся эта религия UnixWay и его патриархов благополучно загнивала в бубунтах школоло-линускоидов, и она нахуй никому не была бы нужна, если бы гугл, запиливая никому не нужный язычок программирования, не купил бы этому языку Патриарха Томпсона и Патриарха Пайка, явным образом заявив претензию на духовное превосходство своего поделия над Unix и C. И тут вскипели говна…

Во-первых, язычок назвали очень оригинальным словом буржуйским Go, чтобы информацию по нему было бы проще искать в гугле, и чтобы он не путался с китайской игрой Го, и чтобы никто не подумал бы, что язык Go имеет какое-либо хоть самое отдалённое отношение к другому проекту гугла — AlphaGo. Во-вторых, язык сделали абсурдно простым, чтобы любой школотрон мог бы пилить на нём микросервисы и хвастаться ими перед тёлками. В-третьих, пошли слухи о том, что Go заменит C и C++. Впоследствии эти слухи были признаны дезинформацией, видимо агент 007 попутал Go и Rust в своём донесении, или может это был холодный расчёт гугла, чтобы отвлечь диванную роту обороны от реальной цели — пайтона. Но, как бы там не было, шороху эти слухи понаделали немало.

Собственно вот и вся история. А вы чего хотели, от языка в подростковом возрасте, которому ещё и 20 нет? Сегодня гугл продолжает накручивать Go рейтинги TOIBE, с каждым годом прикупая всё более и более высокие позиции, и распускает слухи о том, что на Go пишут 100500 специально обученных программистов.

Суть[править]

Патриархи когда-то запилили кошерный C, и когда впоследствии Страуструп запилил C++, им этот C++ был как серпом по яйцам. Они терпели 20 лет, но потом терпение кончилось, и они выкатили Go. Для этого они сделали шаг назад к C, а потом шаг вперёд, но иначе чем Страуструп. Они не пытались создать «C с классами» или там «С с блекджеком и шлюхами», они создали новый язык, который заимствует конечно из C довольно много, в частности, синтаксис, но при этом совершенно иной. Парадигма «zero cost abstractions», благодаря которой C претендовал в своё время на звание кроссплатформенного ассемблера, пошла лесом. Например, ручное управление памятью пошло лесом, и в гошечке памятью ворочает сборщик мусора.

Чтобы перетянуть в свой язык хипстеров, жрущих смузи вилками, Патриархи натолкали в Go всяких няшностей, таких как:

  • вывод типов (type inference), то есть тип для переменной надо указывать только тогда, когда компилятор сам не может догадаться;
  • утиную типизацию (duck typing), «if it walks like a duck and it quacks like a duck, then it must be a duck» (надм. если это переваливается как утка и квакает как утка, то это — утка), в смысле, если значение ведёт себя как int, то это значение типа int и ниибёт. Впрочем, патриархам это было обидно, и они изобрели новый термин «structural typing», который означает «duck-typing в Go»;
  • пакетный манагер, пакеты накатывать на свой проект легко и просто, в стиле этих ваших жабоскриптов с энпээмами.

Вины[править]

Go завоевал свою популярность, благодаря тому, что не всё так плохо.

Простота языка[править]

Сложность изучения Go под стать сложности какого-нибудь там python'а. Простой синтаксис, без тысяч lisp'овых скобок, без зубодробительных темплитов C++, без матана из Haskell'а. Статическая типизация вместе со сборщиком мусора и некоторыми другими мелочами позволяют Go претендовать на memory safety, то есть чтобы отстрелить себе ногу надо хотеть отстрелить себе ногу, если же выполнять простейшие гигиенические правила, то нога останется там, где она сейчас.

Встроенная система сборки со встроенным пакетным манагером с центральным репозиторием, которая скачивает и собирает зависимости проекта по своей инициативе, ей даже напоминать не надо избавляет от соблазнов изобретать велосипеды, с которыми лишь редкие C/C++ программисты могут справится.

Анально-навязанные правила форматирования кода тоже помогают не изобретать велосипед. У программистов вырабатывается со временем аутистичная профдеформация, которая приводит к неконтролируемым вспышкам ярости в ответ на код, отформатированный согласно правилам отличным, от тех, к которым программист привык. Если в каком-нибудь уютном чятике где тусят C или C++ программисты стало скучно, достаточно вбросить какое-нибудь мнение о том, как надо правильно форматировать код, и вот уже жара пошла, программисты с искрами из глаз будут доказывать, что открывающую фигурную скобочку надо ставить на отдельной строке, или что ставить пробел между идентификатором и открывающей скобочкой может только полный мудак. В Go ничего такого нет и не предвидится, потому что есть официальный стиль форматирования и пока не появится какой-нибудь лжепророк, который сможет протолкнуть в массы альтернативный стиль, троллить гошников форматированием не удастся.

Async IO[править]

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

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

Так вот, но Go внезапно, решает все эти проблемы. В принципе их и без Go решали, но для этого надо было обладать чёрным поясом программирования на C и при этом быть невъебенным системным программистом. Надо было уметь переключать контексты вручную, не допускать блокировок, ходить по граблям race condition, и вообще по всякому унижаться. В Go же достаточно уметь набрать слово go, и проблема магическим образом решается.

Срачи[править]

Язык Go своим реактивным взлётом, породил ряд срачей, которые нельзя не упомянуть всуе.

В Go нет дженериков[править]

На самом деле нет! Вместо этого предлагаются такие варианты, как использование кодогенерации (когда пишешь шаблон, а по нему тебе создадут миллионы функций вида SortStrings(), SortInts() и тд). Ещё совсем недавно можно было придти в любое обсуждение Go и бодро заявить "в го нету дженериков", а затем покормиться разными мнениями о том, что Пайк обещал дженерики вот буквально вчера. Обещают запилить дженерики в версии Go 2.0. Можно спровоцировать вялотекущий срач дженерики vs interface (то есть vs ООП Go Edition), или дженерики vs макроподстановки.

UDP: в Go 1.18 таки запилили. Теперь полиморфизм можно ограничить явно с помощью т.н. type constraints путём тупого перечисления всех входящих в ограничение типов:

type Constraint interface {
    // Type1 | ~Type2 | ...
}

func Func[Cons Constraint](arg Cons) {
    // ...
}

Обработка ошибок[править]

Патриархи с завистью смотрели на try-catch во всяких этих ваших C++ да Java, но связываться с размоткой стека структурной обработки ошибок не решились. Интересные side-эффекты C++ с ошибками выкидывающими ошибки из деструкторов деструкторов их испугали. Но, горький опыт C, показал, что без обработки ошибок, всё же никак. Поэтому в Go ошибки такие же значения как и всё остальное, а значит делать с ними можно что хочешь: возвращай из функций, сохраняй в переменные, передавай аргументами в функции, печатай, меняй текст, склеивай ошибки в одну и тд. Но так как ошибки все равно надо обрабатывать, то вместо всем надоевшим блоков try-catch, на Go теперь вынуждены на каждый пук писать

err := MyFunc()
if err != nil {
    return err
}

На самом деле у подобного механизма обработки ошибок есть как минимум два неиллюзорных преимущества:

  • Самодокументация кода. Достаточно посмотреть на сигнатуру функции, чтобы понять, что она может упасть с ошибкой, а следовательно с этим нужно что-то делать. При этом в рамках самой сигнатуры это выглядит лаконично, что не скажешь о джавоских public static void hui(Pizda pizda) throws PolshestogoException {} и аналогичных костылях в плюсах.
  • Программиста буквально заставляют обращать внимание на возможные ошибки, постоянно напоминая о важности их обработки. Например, в Питоне, чтобы открыть файл, достаточно написать что-то такое:
    fp = open('file.txt', 'r')
    
    В сравнении с Го:
    fp, err := os.Open("file.txt")
    
    В первом случае обработка ошибок заметается под ковер с перспективами когда-нибудь вернуться к ней (навесить один большой внешний try-catch блок). Во втором случае, дабы обойти острую необходимость как-то обработать возвращаемую ошибку здесь и сейчас, нужно явно сказать компилятору, что мне похуй на закон и писать конструкции такого вида (которые являются полным моветоном):
    fp, _ := os.Open("file.txt") // явно игнорирует второе значение
    
    Либо получить в лицо ошибку компиляции из-за неиспользованной переменной err. В конечном счёте сам язык заставляет программиста всегда держать обработку возможных ошибок в голове.

Go убийца C++[править]

Срач, который возник на ровном месте. Из Go такой же убийца C++, как и из D: язык со сборкой мусора никогда не сможет не то что убить C++, он даже не сможет приблизиться на расстояние выстрела в ногу. Возможно всё дело в маркетинговом буллшите гугле, которым тот утверждал, что пиздец инновационный generational сборщик мусора в Go работает чуть ли не быстрее, чем отсутствие сборки мусора. Такого рода заявления, как легко видеть, подрывали основу доминирования C++, и поэтому вызывали лютый баттхёрт в стане C++ и острое желание опровергнуть. На поверку вышло, что сборщик мусора, хоть и generational, но довольно быстрый. Впрочем это не помогло ему быть достаточно быстрым, чтобы Go мог бы конкурировать с C++. Fail.

Go убийца Python[править]

Go действительно напоминает Python по простоте написания программ, и при этом в нём нет GIL и структурирования кода пробелами. При этом Go из коробки компилируемый, статически типизируемый и поэтому быстрее. Другое дело, что датассайнс и ссайнс в целом используют пайтон и не парятся, им глубоко насрать на скорость пайтона, потому что обширные вычислительные библиотеки пайтона написаны на C. А больше им ничего и не надо.

См. также[править]

Movax1010h.png Глубокий смысл скрыт в этих неестественных языках
Языки программированияПромышленные: BATC#CC++JavaJavaScript (AJAX) • PascalPerlPHPPythonRubyABAPАссемблерВасикFortran (Профессор)
Эзотерические: BrainFuckHQ9++ErlangForthHaskellLISP (My other car) • PrologTclΤΕΧOracleMySQLGolangВ++Scala
ПрофессииБыдлокодерПрограммистТестировщикХакерХеллоуворлдщикIT-звёзды
Методы и стилиReverse EngineeringАнти-паттернВыстрелить себе в ногуГрязный хакКод (индусский) • КостыльМетод научного тыкаПомолясьСвистелки и перделкиОчередьСпортивное программированиеОбфускацияБета-тестАльфа-тестШаблоныRegReplace
Средства разработкиSublime TextПодсветка синтаксиса кодаUnstable DiffusionAPIPythonTutorCodeWarsDataCampUnity3D
ЛюдиИлья КанторЮрий КлючевскийЭдуард Лаас
Прочее++i + ++iDeadline%s640 килобайтCMSDummy modeЕГГОГFoobarGod is real, unless explicitly declared as integerGOTOIfconfigKISSRegExpSICPsql.ruXyzzyДискетаИнжалид дежицеКОИ-8ЛогМанРекурсияСУБДТест ТьюрингаУмение разбираться в чужом кодеФаза ЛуныФатальный недостатокПроблема 2000ТаймстампКэшЗапись в файл без кэша (Perl)Танцы с бубномКодач