Назад

Go (часто также Golang) — компилируемый многопоточный язык программирования, разработанный внутри компании Google. Разработка Go началась в сентябре 2007 года, его непосредственным проектированием занимались Роберт Гризмер, Роб Пайк и Кен Томпсон, занимавшиеся до этого проектом разработки операционной системы Inferno. Официально язык был представлен в ноябре 2009 года. На данный момент поддержка официального компилятора, разрабатываемого создателями языка, осуществляется для операционных систем FreeBSD, OpenBSD, Linux, macOS, Windows, DragonFly BSD, Plan 9, Solaris, Android.. Также Go поддерживается набором компиляторов gcc, существует несколько независимых реализаций. Ведётся разработка второй версии языка.

 

Назначение, идеология

Язык Go разрабатывался как язык программирования для создания высокоэффективных программ, работающих на современных распределённых системах и многоядерных процессорах. Он может рассматриваться как попытка создать замену языкам Си и C++. По словам Роба Пайка, «Go был разработан для решения реальных проблем, возникающих при разработке программного обеспечения в Google». В качестве основных таких проблем он называет:

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

Основными требованиями к языку стали:

  • Ортогональность. Язык должен предоставлять небольшое число средств, не повторяющих функциональность друг друга.
  • Простая и регулярная грамматика. Минимум ключевых слов, простая, легко разбираемая грамматическая структура, легко читаемый код.
  • Простая работа с типами. Типизация должна обеспечивать безопасность, но не превращаться в бюрократию, лишь увеличивающую код. Отказ от иерархии типов, но с сохранением объектно-ориентированных возможностей.
  • Отсутствие неявных преобразований.
  • Сборка мусора.
  • Встроенные средства распараллеливания, простые и эффективные.
  • Поддержка строк, ассоциативных массивов и коммуникационных каналов.
  • Чёткое разделение интерфейса и реализации.
  • Эффективная система пакетов с явным указанием зависимостей, обеспечивающая быструю сборку.

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

В результате получился язык, «который не стал прорывом, но тем не менее явился отличным инструментом для разработки крупных программных проектов».

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

 

Основные возможности языка

Основные возможности языка Go:

  • Go — язык со строгой статической типизацией. Доступен автоматический вывод типов, для пользовательских типов — «утиная типизация».
  • Полноценная поддержка указателей, но без возможности применять к ним арифметические операции, в отличие от C/C++/D.
  • Строковый тип со встроенной поддержкой юникода.
  • Использование динамическихмассивов, хеш-таблиц, срезов (слайсов), вариант цикла для обхода коллекции.
  • Средства функционального программирования: неименованные функции, замыкания, передача функций в параметрах и возврат функциональных значений.
  • Автоматическое управление памятью со сборщиком мусора.
  • Средства объектно-ориентированного программирования, но без поддержки наследования реализации (наследуются только интерфейсы). По большому счёту, Go является процедурным языком с поддержкой интерфейсов.
  • Средства параллельного программирования: встроенные в язык потоки (go routines), взаимодействие потоков через каналыи другие средства организации многопоточных программ.
  • Достаточно лаконичный и простой синтаксис, основанный на Си, но существенно доработанный, с большим количеством синтаксического сахара.

Go не содержит целого ряда популярных синтаксических средств, доступных в других современных языках прикладного программирования. Во многих случаях это вызвано сознательным решением разработчиков. Краткие обоснования выбранных проектных решений можно найти в «Часто задаваемых вопросах»[4] по языку, более подробные — в опубликованных на сайте языка статьях и обсуждениях, рассматривающих различные варианты дизайна. В частности:

  • Структурная запись обработчиков исключенийсочтена провоцирующей на пропуск ошибок или неадекватную их обработку. К тому же поддержка исключений серьёзно усложняется в приложениях с параллельно работающими частями. Вместо неё предлагается проверка кодов возврата с использованием многозначных функций и специального интерфейса error, а также применение отложенных (deferred) функций для перехвата исключительных ситуаций.
  • Наследование реализации, как считают авторы, приводит к созданию кода с неявными зависимостями, избыточно сложного в поддержке. Аналогичные возможности, но без свойственных наследованию нежелательных эффектов, обеспечиваются поддержкой вложения типов и свободно определяемыми интерфейсами.
  • Обобщённое программирование. Авторы воздержались от его включения в первую версию языка, поскольку, по их словам, предоставляемые им возможности не окупают требуемого усложнения компилятора и runtime-библиотек, а уже имеющиеся в языке средства (пустые интерфейсы, «утиная типизация» и рефлексия) позволяют создавать обобщённый код без специальных синтаксических механизмов. Тем не менее, обсуждается вопрос о включении таких средств в проектируемую вторую версию языка, выход которой запланирован на 2019 год.
  • Использование утверждений (assertion)было сочтено ненужным.
  • Переопределение методов и функцийбыло исключено из соображений надёжности и эффективности компиляции: требование различного именования всех методов на одном уровне видимости устраняет необходимость сопоставлять списки параметров при компиляции вызовов функций и методов и исключает ошибочный вызов другого одноимённого метода; при этом сама возможность переопределения есть не более чем синтаксический сахар.
  • Ряд операций над массивами и срезами (например, вставка элемента в середину) не включены в язык, поскольку они достаточно затратны. Возможность их выполнения одной простой командой провоцировала бы программиста на создание неэффективного кода, отсутствие таких команд в языке, напротив, является стимулом для рассмотрения альтернативных решений.
  • Поддержка отрицательных индексов, доступная в ряде популярных языков, может стать причиной труднообнаруживаемых ошибок: появление отрицательного индекса из-за ошибки в коде вместо того, чтобы привести к фатальному сбою, вызовет внешне корректное обращение не к тем элементам массива, что проявится только в неверных результатах и может быть обнаружено далеко не сразу.
  • Принцип «любое выражение возвращает значение» провоцирует программиста на создание сложных, трудно воспринимаемых и чреватых неочевидными ошибками выражений (вроде копирования строки на Си командой из трёх слов: while (*ptr1++ = *ptr2++);). Практической необходимости в таком усложнении сейчас нет: современный оптимизирующий компилятор оттранслирует и экстремально сокращённое выражение, и аналогичный по функциональности фрагмент, написанный безо всяких ухищрений, в одинаково эффективный машинный код.

 

У вас нет прав для комментирования.