Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Go

3 отличия Go

by
Read Time:7 minsLanguages:

Russian (Pусский) translation by Alex Grigorovich (you can also view the original English article)

Go — это специальный язык. Он новый в своем подходе к программированию и в принципах которые он использует. Этому способствовало то, что некоторые из создателей языка изобретателей пионеры C. Общее ощущение Go, это C 21-го века.

В этом уроке вы узнаете о трёх особенностях, которые делают Go уникальным: это его простота, модель параллелей с помощью goroutines и механизм обработки ошибок.

1. Простота

Многие успешные современные языки, такие как Scala и Rust очень мощные и предлагают продвинутые системы типов и системы управления памятью. Эти языки взяли за основу популярные языки их времени, таких как C++, Java и C# и добавили или улучшили их возможности. Go идёт по другому пути и исключает многие особенности и возможности.

Нет шаблонам

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

Это, возможно, самое спорное решение создателей Go. Лично я вижу много хорошего в шаблонах и верю, что это может быть сделано правильно (см. C#, как пример хороших шаблонов сделанных правильно). Надеюсь, что в будущем, шаблоны будут использоваться в Go.

Без исключений

Обработка ошибок языка Go опирается на коды исключений. Чтобы отделить статус от результата функции, Go поддерживает множественные возвращаемые значения в функциях. Это довольно необычно. Я расскажу об этом подробнее чуть позже, ниже небольшой пример:

Один исполняемый файл

В Go нет отдельной исполняемой библиотеки. Он генерирует один исполняемый файл, который можно развернуть только путем копирования (типо развертывание XCOPY). Это так же просто, как и выглядит. Не нужно беспокоиться о зависимостях или несоответствиях версий. Это большое чудо для контейнерного развертывания (Docker, Kubernetes и его приятелей). Один исполняемый файл упрощает работу с Dockerfiles.

Нет динамических библиотек

Отлично. Это недавно изменилось в Go 1.8. Теперь вы можете загружать динамические библиотеки с помощью расширений. Но, так как эта возможность не была представлена в Go сначала, я применяю расширение только в особых случаях. Суть Go в статически скомпилированном исполняемом файле. Это доступно только для Linux.

2. Goroutines

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

CSP

Основа модели параллелей в Go является C. A. R. Связи последовательных процессов Hoar. Идея заключается в том, чтобы избежать синхронизации через общую память между несколькими потоками выполнения, которая является трудоемким процессом и приводит к ошибкам. Вместо этого взаимодействие проходит через каналы, которые избегают соперничества.

Вызов функции как Goroutine

Любая функция может быть вызвана как goroutine через ключевое слово go. Рассмотрим следующую линейную программу. Функция foo() бездействует несколько секунд и выводит сколько секунд она "спала". В этой версии, каждый вызов foo() блокируется до следующего вызова.

Результат соответствует порядку вызовов в коде:

Теперь я сделаю небольшие изменения и добавлю ключевое слово «go» до первых трех вызовов:

Результат теперь отличается. 1 второй вызов заканчивает первым и выводит на экран «1s», затем идут «2s» и «3s».

Обратите внимание, что 4 второй вызов не является goroutine. Так и задумано, поэтому программа ждёт и позволяет goroutines завершить работу. Без него программа завершится сразу после запуска goroutines. Существуют различные способы кроме "засыпания" подождать пока goroutine завершит выполнение.

Синхронизация Goroutines

Еще один способ ожидания пока goroutines завершит выполнение, это использование групп синхронизации. Вы объявляете объект ожидания группы и передаёте его в каждый goroutine, который отвечает за вызов метода Done(), когда задача выполнена. Затем вы ожидаете группы синхронизации. Вот код, который адаптирует предыдущий пример для использования его как группы ожидания.

Каналы

Каналы позволяют goroutines (и вашу главную программу) обмениваться информацией. Вы можете создать канал и передать его в goroutine. Создатель может записывать в канал, а goroutine может читать из канала.

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

Пишем Goroutine

Это своего рода трюк. Написание goroutine такое же, как и написание любой функции. Посмотрите функцию foo() выше, которая вызывается в программе как goroutine, и как обычная функция.

3. Обработка ошибок

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

Существует также механизм, который напоминает исключения с помощью функций panic() и recover(), но это лучше всего подходит для особых ситуаций. Вот типичный сценарий обработки ошибок, где функция bar() возвращает ошибку, и функция main() проверяет, произошла ли ошибка и печатает ее.

Обязательная проверка

Если вы присвоили переменной ошибку и не проверили её, Go расстроится.

Есть способы обойти его. Вы можете просто не назначать ошибку вообще:

Или можно назначить её через подчеркивание:

Языковая поддержка

Ошибки это значения, которые вы можете пропускать свободно. Go предоставляет небольшую поддержку ошибок, объявляя интерфейс ошибок, который требует метод по имени Error() и возвращает строку:

Существует расширение errors, которое позволяет вам создавать новые объекты ошибок. Расширение fmt предоставляет функцию Errorf() для создания форматированных объектов ошибки. Это о нём.

Взаимодействие с Goroutines

Вы не может возвращать ошибки (или любой другой объект) из goroutine. Goroutines могут связывать ошибки с внешним миром через посредников. Передача канала ошибки в goroutine считается хорошей практикой. Goroutines также могут записывать ошибки в файлы журнала или в базу данных или вызывать удаленные службы.

Заключение

Go приобрёл огромный успех и динамику за последние годы. Это язык "идти и глянь" (см. то, что я там сделал), для современных распределенных систем и баз данных. У него есть много разработчиков перешедших с языка Python.

Большая часть его несомненно объясняется поддержкой компании Google. Но Go определенно "стоит на своём". Его подход к разработке основных языков очень отличается от других современных языков программирования. Дайте ему шанс. Его очень легко освоить и весело программировать.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.