что можно написать на golang
Если вы подумываете начать писать на Go, то вот что вам следует знать
Ваш любимый питомец пишет на Go и получает больше вас, а вы ещё нет? Не теряйте времени… Такая мысль может родиться у читателя от обилия статей по Go. Некоторым даже компании предлагают переучиться на этот язык. И, если вы хоть раз задумывались освоить язык, то я хочу вас предостеречь. Вернее показать странные вещи, попробовать объяснить зачем они и потом вы уже сами сделаете вывод нужен ли вам Go.
Для кого эта статья
Статья в первую очередь предназначена тем людям, для которых важна выразительность языка. И одновременно для тех, кто хочет пощупать Go.
Я сам Си++/Python разработчик и могу сказать, что это сочетание является один из оптимальнейших для освоения Go. И вот почему:
Что по-поводу пары Java/C#? Go ей ни разу не конкурент, по крайней мере пока он молод (речь про версию Go 1.11).
Чего не будет в статье
А что будет? Только конкретные случаи дискомфорта, которые доставляет язык в работе.
Начало работы
Хорошим вводным по языку мануалом является короткая онлайн книга Введение в программирование на Go. Читая которую вы довольно быстро наткнётесь на странные особенности. Приведём для начала первую партию из них:
Странности компилятора
Поддерживаются только египетские скобки, то есть следующий код не компилируется:
Авторы считают, что стиль программирования должен быть единообразным и компактным. Чтож хозяин — барин.
Здесь упор идёт на то, что почти всегда это ошибка, связанная или с опечаткой, или спешкой, или кривым рефакторингом. Как бы в конечном коде да, такого быть не должно. Но мы редко пишем сразу конечный код и периодически пробуем запускать промежуточные версии, в которых может быть некоторый задел на будущее. Поэтому данное поведение компилятора напрягает.
Правда со временем возникает множество ситуаций, когда это уберегло от ошибки. Но это всё-равно напрягает.
Неиспользуемые параметры приходится заглушать и это смотрится странно, хотя в питоне так тоже можно:
Но это всё цветочки и даже просто вкусовщина разработчиков. Теперь перейдём к более тяжеловесным вещам.
«Безопасный» язык
И тут надо не забыть сказать об очень важной вещи. Дело в том, что язык сделан именно таким, чтобы неопытным разработчики не имели возможности создавать плохие программы.
Вот цитата одного из создателей языка:
«Ключевой момент здесь, что наши программисты (прим.пер.: гуглеры) не исследователи. Они, как правило, весьма молоды, идут к нам после учебы, возможно изучали Java, или C/C++, или Python. Они не в состоянии понять выдающийся язык, но в то же время мы хотим, чтобы они создавали хорошее ПО. Именно поэтому язык должен быть прост для понимания и изучения.»
Так значит вы говорите безопасный язык?
и после запуска программы получаем:
В этом невинном примере мы «забыли» выделить себе память и получили ошибку времени выполнения. Так а какой безопасности может идти речь, если вы меня не спасли от неверной ручной работы по выделению ресурсов?
Хабраюзер tyderh замечает, что:
Безопасность заключается в том, что при выполнении отлавливается ошибка, а не происходит неопределённое поведение, способное произвольным образом изменить ход выполнения программы. Таким образом, подобные ошибки программистов не способны привести к появлению уязвимостей.
Вызовет ошибку компиляции, что как бы нормально. Но поскольку в Go пока (пока!) нет шаблонов, то очень часто они эмулируются через интерфейсы, что может рано или поздно вылиться в такой код:
Этот код уже компилируется и работает, но не так как ожидает программист. Все три сравнения выдадут false, ибо сначала сравнивается тип интерфейсов, а он разный. И если в данном случае ошибка явно бросается в глаза, в реальности она может быть сильно размыта.
powerman поделился ещё один примером ложных ожиданий:
Интерфейс с nil не равен просто nil, будьте осторожны. В FAQ языка этот момент есть.
Ну и завершая про безопасность. Разыменование в языке убрано, а вот спецэффекты в зависимости от вида доступа от доступа (по указателю или по копии) остались. Поэтому следующий код:
Выведет pen. А следующий:
Выведет «-deleted-«, но пожалуйста, не ругайте сильно программистов, когда они на эти грабли наступят, от этого в «безопасном» языке их не спасли.
а потом вы решили добавить второй параметр возврата, IDE подсказал вам, что теперь надо его ловить, и вам пришлось попутно заменить оператор и вдруг вы видите грабли перед лицом.
А это значит, что теперь нам надо у PVS просить статический анализатор для языка Go.
Краткий вывод: безопасность присутствует, но она не абсолютна от всего.
«Единообразный» язык
Выше в разделе странности компилятора было указано, что при неверном форматировании кода, компилятор упадёт. Я предположил, что это было сделано для единообразия кода. Посмотрим насколько код единообразный.
Вот например, два способа выделить память:
Ну да, ну да, это просто фишка функции new, которую мало кто использует. Ладно будем считать это не критичным.
Вот например, два способа создать переменную:
Ладно, ладно, var используется реже и в основном для резервирования под именем определённого типа или для глобальных переменных неймспейса.
Ладно, с натяжкой будем считать Go единообразным языком.
«Колбасный» код
А вот ещё частая проблема, конструкция вида:
Это типичный кусок кода на Go, назовём его условно колбасой. Среднестатистический код на Go состоит на половину из таких колбас. При этом первая колбаса сделана так result, err := function(), а все последующие так result, err = function(). И в этом не было бы проблемы, если бы код писался только один раз. Но код — штука живая и постоянно приходиться менять местами колбасы или утаскивать часть колбас в другое место и это вынуждает постоянно менять оператор := на = и наоборот, что напрягает.
«Компактный» язык
Когда читаешь книгу по Go, не перестаёшь удивляться компактности, кажется что все конструкции продуманы так, чтобы код занимал как можно меньше места как по высоте, так и по ширине. Эта иллюзия быстро рушится на второй день программирования.
И в первую очередь из-за «колбас», о которых я упоминал чуть выше. Сейчас ноябрь 2018 и все Go программисты ожидают версию 2.0, потому что в нём будет новая обработка ошибок, которая наконец покончит с колбасами в таком количестве. Рекомендую статью по ссылке выше, в ней суть проблемы «колбасного» кода разъяснена наглядно.
Но новая обработка ошибок не устранит все проблемы компактности. По прежнему будет не хватать конструкций in и not in. На текущий момент проверка нахождения в map значения выглядит так:
И единственное на что можно надеяться — на то, что после компиляции это будет скукожено до просто проверки значения, без инициализации попутных переменных.
Молодой язык и бедный синтаксис
К Go существует очень много написанного кода. И есть просто потрясающие вещи. Но не редко вы выбираете между очень плохой библиотекой и просто приемлемой. Например SQL JOIN в одном из лучших ORM в GO (gorm) выглядит так:
А в другом ORM вот так:
Что ставит пока под сомнение вообще необходимость использовать ORM ибо нормальной поддержки защиты от переименования полей не везде просто нет. И ввиду компилируемой природы языка может и не появиться.
А вот один из лучших образцов компактного роутинга в вебе:
Не то чтобы здесь было что-то плохое, но в динамических языках код обычно выглядит более выразительным.
Спорные недостатки
Публичные функции
Угадайте, как сделать функцию публичной для использования в других пакетах? Здесь есть два варианта: либо вы знали или никогда бы не угадали. Ответ: зарезервированного слова нет, нужно просто назвать функцию с большой буквы. В это вляпываешься ровно один раз и потом привыкаешь. Но как питонист помню про правило «явное лучше неявного» и предпочёл бы отдельное зарезервированное слово (хотя если вспомнить про двойное подчёркивание в питоне, то чья бы корова мычала).
Многоэтажность
Если вам нужен словарь объектов, то вы напишите что-то такое:
Пугающая конструкция, не правда ли? Глазу хочется каких-нибудь скобочек, чтобы не спотыкаться. К счастью они возможны:
Но это всё, что позволит вам форматтер go fmt, который почти наверняка будет использоваться в вашем проекте для переформатирования кода при сохранении. Все остальные вспомогательные пробелы будут выпилены.
Атомарные структуры
Их нет. Для синхронизации надо явно использовать мьютексы и каналы. Но «безопасный язык» не будем вам пытаться мешать писать одновременно из разных потоков в стандартные структуры и получать падение программы.
helgihabr любезно напомнил, что в 1.9 появился sync.Map.
Тестирование
Во всех не очень безопасных языках безопасность хорошо реализуется через тестирование с хорошим покрытием. В Go с этим почти всё в порядке, кроме необходимости писать колбасы в тестах:
Понимая ущербность данного подхода, мы сразу нашли в сети библиотеку, реализующую assert и доработали её до вменяемого состояния. Можно брать и использовать: https://github.com/vizor-games/golang-unittest.
Теперь тесты выглядят так:
Две конвертации типов
В языке сущность интерфейса имеет особый статус. Они в том числе часто используются, чтобы заткнуть «бедность» синтаксиса языка. Выше уже был пример с реализацией шаблонов через интерфейсы и неявным вредным спецэффектом, порождённым этим случаем. Вот ещё один пример из этой же серии.
Для преобразования типов можно использовать обычную конструкцию в Си-стиле:
Но не пытайтесь применить её к интерфейсам, ибо для них синтаксис другой:
И это довольно долго будет вас путать. Я для себя нашёл следующее правило для запоминания.
Преобразование слева называется conversion, его корректность проверяется при компиляции и в теории для констант может производится самим компилятором. Такое преобразование аналогично static_cast из Си++.
Преобразование справа называется type assertion и выполняется при выполнении программы. Аналог dynamic_cast в Си++.
Исправленные недостатки
Пакетный менеджер
vgo одобрен, поддерживается JetBrains GoLand 2018.2, для остальных IDE как временное решение подойдёт команда:
Да, это выглядит как небольшой костыль сбоку, но это отлично работает и просто реализует ваши ожидания по версионированию. Возможно в go2 этот подход будет единственным и нативным.
В версии 1.11 эта штука уже встроена в сам язык. Так что верной дорогой идут товарищи.
Достоинства
мы сразу сообщаем рантайму, что, в независимости от того каким и где будет выход из функции, в конце надо выполнить определённый код. Это сразу частично решает проблему с отсутствием деструкторов и почти полностью решает проблему отсутствующих контекстов (например питоновский with).
Почему так получилось
Go выглядит как надмножество Си. Об этом говорит очень многое: и похожесть синтаксиса и понимание того, как это может быть легко преобразовано в Си код. Конечно же горутины, сборка мусора и интерфейсы (а вместе с ним RTTI) нетипичны для Си, но весь остальной код легко конвертируется практически регулярками.
И вот эта природа, на мой взгляд, и диктует почти все приведённые выше странности.
Резюме
Что делает Go таким необычным?
Авторизуйтесь
Что делает Go таким необычным?
Сегодня Go — один из самых востребованных языков программирования. Вот секретный ингредиент его успеха.
Введение
Очевидно, что языки программирования можно рассматривать как основной инструмент в арсенале каждого разработчика. Мы склонны считать себя в некотором роде особенными. То есть формируем сообщества, пишем статьи, делаем видео на YouTube, маскоты и, что более важно — мемы. Шучу. Но всё же трудно отрицать существование некой тесной, почти личной связи между нами и этими абстрактными инструментами.
Как вы, наверное, догадываетесь, эта статья одна говорит о распространённом, новаторском и довольно необычном языке программирования под названием Go. Чтобы соответствовать Go — быть простым, полезным и нетривиальным — я не буду пересказывать то, что уже написано другими. А скорее попытаюсь сформировать новое видение — проанализировать дизайн, историю появления и особенности языка Go, а также, наконец, рассказать, где его лучше использовать.
Краткий обзор
Вот тезисы, которые дадут прочувствовать Go:
Теперь давайте рассмотрим каждый из пунктов подробно.
Контекст создания
Чтобы понять природу Golang, давайте взглянем на контекст создания. Однажды компания Google столкнулась с проблемами, которые не получилось решить с помощью готовых инструментов. Так что Go родился благодаря сильной потребности в изменениях:
Цели проекта Go состояли в том, чтобы сделать разработку программного обеспечения в Google не такой неуклюжей и медлительной. И вместе с тем сделать сам процесс более продуктивным и масштабируемым. Этот язык разработали люди, которые пишут, читают, отлаживают и поддерживают большие системы, — Роб Пайк, создатель Golang.
Как уже было сказано, Go разрабатывали, с учётом набора пока нерешённых задач. А также изначально вложили в него базу лучших функций, взятых из C, Pascal, Modula и Oberon. К тому же создатели ориентировались на полезные фишки Python, C++, Java и т. д. — критику которых Go был призван устранить.
Ограничения языка
Речь никогда не шла о копировании того, что уже было. Скорее о том, чтобы придумать новый способ решения проблем. Иногда для того, чтобы решить вопрос, требуется изучить старые, неэффективные методы и отказаться от них. И потому важные особенности языка Go возникли из его основных ограничений. Например:
Как видим, разработчикам Go удалось придумать эффективную систему языковых ограничений и получить набор отличительных характеристик и возможностей. Эта впечатляет: используя каждое из ограничений, язык приходит не к одной, а сразу к нескольких характерным чертам.
Должен отметить, что метод определения особенностей языка Go на основе ограничений, к которому я здесь прибегаю, основан не только на цитатах его создателей, блогах и речах, а также официальной документации и статьях других авторов. По сути, это личный способ понимания и описания природы и уникальности Golang. Конечно, можно согласиться, либо не согласиться с моей точкой зрения и любить или ненавидеть этот язык абсолютно нормально. Более того, я призываю не верить наслово, а провести собственное исследование этой темы.
25–27 ноября, Онлайн, Беcплатно
Также на этом этапе становится ясно, что Go не похож на другие языки. Те обычно развиваются, добавляя новые функции, усложняя себя, а затем разбираясь с проблемой. Go же ограничен с самого начала.
Многие новички, переходят на Go и требуют включить особенности из языков, которые они уже знают. Но эти особенности не принадлежат Go, и язык фиксирован. Добавление новых функций не сделало бы его лучше — просто больше. Он остаётся интересным, благодаря ограниченности, — Роб Пайк, создатель Golang.
Особенности языка Go
Ограничения не означают, что Go неполный или не пригоден для выполнения некоторых задач. Так можно назвать все программирования бесполезным — ведь «почему бы не пользоваться языком ассемблера?». У Go есть свои особенности. Дело в том, для простоты он сознательно отказался от функций, которые усложняют язык, но не решают конкретные проблемы. По сути, это и сделало Go своеобразным.
Так что же насчёт функций, которые сумели стать частью Go? Ну, на самом деле, правило преднамеренной простоты действует и на них. Я имею в виду, создатели Golang проделали невероятную работу чтобы сделать нечто лёгкое в использовании, на первый взгляд, но сложное «под капотом».
Go сложен. Это, на самом деле, одна из самых сложных вещей, над которыми я когда-либо работал, и всё же она кажется простой… Это потребовало долгого проектирования, обдумывания, труда, связанного с реализацией, и доработок. Простота — это искусство скрывать сложность! — Роб Пайк, создатель Golang.
Давайте посмотрим на «простые» вещей в Go:
Да Go не самый быстрый язык программирования — ведь у нас есть Rust, Julia, C++и C. Но у них нет сборщика и поэтому они даже близко не так просты, как Go. Также часто лёгкость достигается благодаря следующей фишке.
Отражения иногда можно намеренно избегать в пользу другой парадигмы Golang — кодогенерации, которая с точки зрения идеологии Go более ясна и эффективна. Я лично думаю о ней как о «белой магии» и, конечно же, буду отстаивать её преднамеренное использование. Ведь иногда она открывает волшебные возможности, хотя и не так эффективна.
Ну вот и всё. Набор функций Golang — результат продуманного решения серьёзной проблемы языкового дизайна — выбора только правильных функций без усложнения и языка и с сохранением ясности.
Простоту очень трудно спроектировать. Но если сделаете это правильно, получите то, что легко использовать. И успех Go это доказывает! — Роб Пайк, создатель Golang.
Область Применения
Итак, теперь ясно, что у языка Go есть некоторые особенности. Также он прост в использовании, быстр и продуктивен. Но в каких областях он особенно полезен? Что можно сделать благодаря ему?
Некоторые классические языки программирования, такие как C# и Java, за время существования сумели пробраться практически во все области разработки приложений. Так что конкурировать с ними сложно. Но Go и не пытается это сделать. Его создали с конкретной целью, и он по определению не является языком общего назначения.
Однако, на самом деле, цель, «вроде как, одна».
Видите ли, несмотря на то, что изначально Google сделал язык для разработки своего софта и обслуживания собственной среды, как только Go стал проектом с открытым исходным кодом и быстро расширил сообщество, стало ясно, что программисты хотят использовать его для гораздо большего количества задач. С выпуском Go 1 он считается языком общего назначения.
Но на этом процесс обобщения Golang не закончился. Сообщество становится больше, расширяет область использования языка и продолжает создавать новые инструменты, пакеты, фреймворки, драйверы, API, генераторы кода и ещё более удивительные вещи, которые заставляют новых разработчиков верить, что Go действительно может стать их следующим основным языком. Совсем как в моем случае!
Давайте посмотрим, на что способен Go:
И некоторые не особенно очевидные случаи использования:
На данный момент сфера применения Golang явно больше ориентирована на облачное, веб- и системное программирование. Но благодаря энтузиазму, инициативности и активности сообщества Go неуклонно пробивает путь почти во все сферы IT-индустрии.
Заключительные Мысли
Я пользуюсь Go уже почти год, и всё ещё очарован им. Работать на нём — потрясающе, особенно, когда вы можете наблюдать, как благодаря ему производительность растёт.
Идеология, лежащая в основе Go — это признание того, что написание кода часто — меньшая часть процесса разработки. Потому язык избавился от излишней выразительности, ради простоты, ясности и эффективности других важных аспектов работы: обслуживания, просмотра, чтения и редактирования кода.
Думаю, разработчики Golang проделали невероятный труд по проектированию и реализации проекта — в результате мы получили один из самых удобных и экономически эффективных языков. Создатели искали способ повысить скорость и продуктивность разработки и обслуживания больших кодовых баз, и потому Go стал отличным инструментов повышения производительности.
Чтобы подытожить рассказ об уникальности Golang и помочь разобраться, подходит ли вам этот язык, я хотел бы привести главный для себя тезис из идеологии Go, ещё раз процитировав его создателя:
Базовый компромисс в Go — вопрос, к которому подошли иначе, чем в других языках — Чего вы хотите: язык, с которым веселее или проще работать? — Роб Пайк, создатель Golang.
Начало программирования в Go — что нужно знать?
Go является компилируемым языком программирования со статической типизацией. Команда разработчиков дизайна и SDK состоит из специалистов с многолетним опытом в сфере программирования.
У Go есть много характерных черт. Некоторые уникальны, прочие заимствованы из других языков программирования:
Рекомендуем вам супер TELEGRAM канал по Golang где собраны все материалы для качественного изучения языка. Удивите всех своими знаниями на собеседовании! 😎
Мы публикуем в паблике ВК и Telegram качественные обучающие материалы для быстрого изучения Go. Подпишитесь на нас в ВК и в Telegram. Поддержите сообщество Go программистов.
Кроме того, не лишним будет отметить следующие аспекты языка:
Программистов Go часто называют сусликами (англ. gophers). Этот зверек также является логотипом данного языка программирования. Далее в статье мы будем использовать английский вариант термина — гофер.
Хотя Go является компилируемым языком со статической типизацией, в нем также есть довольно много функций, присущих динамическим скриптовым языкам. Затея объединить эти два типа языков может показаться сомнительной, но у Go все получилось довольно неплохо. Иными словами, Go владеет как строгостью статических языков, так и гибкостью динамических языков. Нельзя сказать, что процесс работы обходиться без компромиссов, но преимущество такой комбинации восполняет минусы сполна.
Читабельность является важным фактором, что влияет на дизайн Go. Одному гоферу нетрудно понять код Go, написанный другим гофером.
Компиляторы в Golang
В настоящее время самый популярный компилятор Go написан на Go и поддерживается командой разработчиков Go. Позже он будет упоминаться, как стандартный компилятор Go, или gc (англ. Go compiler). Не путайте с другим GC — garbage collection, или сборка мусора. Команда разработчиков Go поддерживает еще один компилятор Go — gccgo. В настоящее время его использование менее популярно, чем gc. Тем не менее, оба компилятора находятся в активной разработке. На данный момент команда Go занимается улучшением gc.
gc поставляется с официальным Go SDK. Go SDK 1.0 был выпущен в марте 2012 года. Версия Go совместима с версией Go SDK. Это две основные версии языка, выпущенные с разницей в год.
После релиза Go 1.0, синтаксис Go немного изменился, было много улучшений для инструментов в Go SDK, особенно для gc. Например, заметные лаги, вызванные сборкой мусора, являются распространенной проблемой для языков с автоматическим управлением памятью. Однако, начиная с Go 1.8, улучшения, внесенные с реализацией параллельной сборки мусора в gc, по большей части устранили проблему задержки.
gc поддерживает кроссплатформенную компиляцию. К примеру, мы можем создать исполняемый файл Windows на ОС Linux и наоборот.
Большинство программ, написанных на Go, компилируются довольно быстро. Время компиляции является важным фактором успешного развитии. Короткое время разработки — одна из причин, почему многим программистам нравится программировать на Go.
Преимущества исполняемых файлов Go:
Некоторые другие компилируемые языки, такие как C/C++/Rust также обладают данными преимуществами, в каких-то аспектах выигрывают в сравнению с Go. Однако у Go перед ними есть свои плюсы:
Все перечисленные выше преимущества делают Go отличным языком и хорошим выбором для самых разных проектов. В настоящее время Go широко используется в сетях, системных инструментах, разработке баз данных и в блокчейне. В последнее время все большее число разработчиком используют Go для создания игр, проектов с большими объемами данных и ИИ.
Конечно, Go вовсе не идеален. В дизайне Go есть определенные минусы. Особенно это заметно с текущей версией Go 1. К примеру, Go не поддерживает произвольные неизменяемые значения. Это приводит к тому, что многие значения, не предназначенные для изменения в стандартных пакетах, объявляются как переменные. Это потенциально слабое место в безопасности программ Go. Go также не поддерживает дженерики для пользовательских типов и функций. Авторы Go не против введения пользовательских дженериков в Go. Они все еще в процессе поиска оптимального решения, что может сделать Go максимально понятным и простым.
Администрирую данный сайт с целью распространения как можно большего объема обучающего материала для языка программирования Go. В IT с 2008 года, с тех пор изучаю и применяю интересующие меня технологии. Проявляю огромный интерес к машинному обучению и анализу данных.
E-mail: vasile.buldumac@ati.utm.md
Образование
Технический Университет Молдовы (utm.md), Факультет Вычислительной Техники, Информатики и Микроэлектроники