Новый язык Google, Go, создан полностью в духе C++, но включает в себя множество типов и конструкций, которые делают его более похожим на Python или JavaScript. Предварительные тесты eWEEK Labs показали, что Go пока несовершенен, но уже на верном пути.
Не столь давно Google объявил о создании нового языка. Названный Go, язык вскоре получил неплохую долю внимания. Язык создан полностью в духе C++, но включает в себя множество типов и конструкций, которые делают его более похожим на Python или JavaScript.
$CUT$ Первое, что обращает на себя внимание – компилятор Go гораздо умнее, чем более привычные компиляторы старого стиля, как те, которые используются для C++. Например, сколько раз вы задавались вопросом: если компилятор C++ может определить, что точки с запятой не хватает, почему он не может просто распознать, где находится конец оператора и двигаться дальше? Конечно, это возможно. И парсер JavaScript, например, если вы опустите точку с запятой, воспримет данный момент совершенно нормально. То же самое и с Go. Вы можете отказаться от запятых, когда они не нужны.
Вы также можете предоставить компилятору Go выяснить тип переменной на основе первоначального объявления – очередное подтверждение тому, что это умный компилятор. (К примеру, если вы определяете строковую константу для переменной, вполне очевидно, что тип этой переменной должен быть строкой, ведь если вы попытаетесь присвоить строку в не-строковую переменную, вы получите ошибку компилятора.)
Однако с другой стороны, в таком способе объявления присутствует ощутимая проблема. Слишком уж легко просто объявлять переменные как попало, на лету, так же, как когда-то писали старые программы на Basic. Подобные этим конструкции упрощают задачу и приводят к написанию грязного кода. Впрочем, это может иметь место в любом языке.
Go богат встроенными типами, такими как и в большинстве других языков. В качестве интересного примера возьмем строки. В отличие от оригинального C (который технически не имел строкового типа, а скорее использовал указатели на массив символов для обозначения строк), в Go строки являются неизменными. Это действительно похоже на многие современные языки, и это то всерьез беспокоит некоторых программистов. Но это всего лишь реальность. И это не значит, что вы не сможете изменить строковую переменную - вы можете назначить различные строки в переменную. Вы просто не можете изменить отдельные элементы строки.
Также в отличие от C, в Go массивы не просто дополняют указатели. Скорее, массивы являются фактическим типом, как и в других современных языках. И – о чем документация Go почти извиняется – в этом языке действительно есть указатели.
Язык также имеет много новых типов, таких как карты, а также особый тип подмассива, называемый «ломтиком» (slice). (Концепция «слайсов» является новой и чуждой очень многим программистам, но в действительности они довольно гибки и полезны).
Конструкции циклов Go имеют достаточно компактную структуру, и конструкция for, например, включает в себя поддержку перебора карт. (Кроме этого, в Go нет циклов while и repeat, только for.)
Исследуя функции в Go, вы действительно начинаете видеть влияние современных скриптовых языков. Функции могут возвращать несколько значений, точно так же, как это делается в Python и PHP. В обоих этих языках вы можете взять список и отправить его элементы прямиком в отдельные переменные буквально одной строкой кода. В Go вы можете указать, что функция может возвращать несколько значений, например, так:
func complex_f1() (re float, im float) {
return -7.0, -4.0
}
Позже вы сможете вызывать такую функцию, получая возвращаемые значения:
x, y = complex_f1()
А вот это интересно: если вам не нужны все значения, вместо создания фиктивной переменной вы можете использовать "пустой идентификатор" (обозначается символом подчеркивания), тем самым игнорируя одно из возвращаемых значений:
x, _ = complex_f1()
Официальная документация показывает и другие, не менее уникальные особенности. Например, этот фрагмент:
a, b = b, a
обменяет две переменные их значениями.
Классы (или нет)
Классы - или то, что используется в качестве классов в Go, выглядят нестандартно, и будет интересно посмотреть, как люди отреагируют на их необычную природу. Чтобы создать класс, сперва вы определяете тип-структуру. Структуры могут содержать только переменные, никаких функций. Для добавления функции к структуре (чтобы получить в результате класс с методами), необходимо создать функцию, которая включает в себя дополнительный параметр, называемый приемником (receiver). Для этого приемника вы и определяете структуру. После этого экземпляры структуры могут вызвать функцию в качестве члена, как и в других объектно-ориентированных языках.
В результате такая конструкция выглядит довольно увлекательно: ваши приемники (то есть типы, которые вы добавляете в методы) не обязательно должны быть структурой. Они могут быть любого типа, включая тип массива или любой из встроенных типов. Конечным результатом является то, что вы можете улучшить встроенные типы, что делает Go настоящим объектно-ориентированным языком сродни чему-то вроде Smalltalk.
Но это не так уж и необычно, если вы работали в C#, который использует методы расширения. Или, если вы работали в JavaScript, это будет напоминать вам о том, как можно использовать прототипы для добавления методов к существующим типам объектов (например, String). Но это скорее уникальный в интуитивно скомпилированный язык. (И это заставляет задаться вопросом, каким образом некоторые программисты это воспримут. Когда в C#, например, были добавлены такие функции, некоторые люди оказались всерьез расстроены, потому что это сделало возможным легко взламывать существующие объекты и создавать запутанный код.)
Еще одна интересный момент в Go – он не поддерживает наследование. Почему нет? Потому что вместо этого он основан на интерфейсах. К этому придется привыкнуть, как и к основанному на прототипах JavaScript.
Параллелизм
Если вы посмотрите техническую спецификацию, вы заметите там ключевое слово “go” (откуда язык и получил свое имя, кроме того факта, что это первые две буквы Google). Сперва можно предположить, что это замена старому оператору goto и пропустить его. Но как раз это и будет ошибкой.
Go поддерживает то, что Google назвал «goroutines» (routines можно понимать как стандартные программы, операции, функции и т.д.). Это в основном сопрограммный подход, но гораздо проще, чем в некоторых других языках. Идея goroutines в целом состоит в следующем: данные могут быть разделены между стандартными функциями, но только одна может получить к ним доступ в каждый отдельно взятый момент времени. Это означает, что подобие флагов (мьютексов) встроено напрямую в совместно используемые данные с помощью так называемых каналов.
Для вызова параллельной функции просто используйте ключевое слово “go”, например так:
go list.Sort();
Дополнительные функции
В Go также полно небольших замечательных функций: объявления могут быть сгруппированы, что удобно и быстро. Операторы прерывания break не являются необходимыми внутри блока switch/case. По умолчанию не используется передача управления подпрограмме, но если это нужно, вы просто добавляете слово "fallthrough" в конец блока case. Весь код основан на пакетах, аналогично тому, как это организовано в Java.
Кроме того, язык включает в себя небольшой, но богатый набор пакетов для обработки таких вещей, как ввод/вывод, регулярные выражения и многое другое. Google извиняется, что список пакетов пока еще невелик, хотя и растет.
Интересно, что язык также не использует утверждения. Это правильно, так как слишком много программистов C/C++ используют утверждения, как опору, в результате получая плохой код. Хорошо написанный код должен правильно обрабатывать ошибки, не затрагивая все остальные строки кода с обращениями к утверждениям.
Наконец, язык включает сборщик мусора, хотя он и компилирован. Наличие сборщика мусора стало камнем преткновения для многих почитателей C++. Но в крупных современных системах сбор мусора скорее необходимость, хотя некоторым это и не нравится.
Заключение
С учетом сказанного, современные языки, как правило, не слишком легкие, и обычно не так быстры, как что-то наподобие C++. Да, уже существуют довольно неплохие компиляторы, которые действительно могут сделать прорыв в программировании в перспективе. Но они все еще редко могут соревноваться с хорошо написанной на C++ программой.
Сейчас Go кажется вполне достойной заменой для C++. Он наделен красотой и простотой современных языков. Он не идеален, он потребует некоторого переучивания, что не всегда просто. Но теперь можно утверждать, что Google движется в верном направлении.
Оригинал на Eweek.com Перевод: Johnny