Данную публикацию я бы хотел посвятить PHP-бэкендерам (навроде меня), которые хотят изучить особенности разработки на языке программирования GoLang (или просто Go), но не знают с чего начать.
Повествование начну с краткой исторической справки, далее в общих чертах расскажу о преимуществах GoLang по сравнению с PHP, затрону вопросы связанные с установкой интерпретатора go, ну и под конец разберу особенности создания приложений через сравнение.
Историческая справка о GoLang
GoLang - это относительно молодой язык программирования, который был создан в Google в 2007 году и официально представлен публике в 2009 году (исходные коды на GitHub).
Язык был разработан командой из трех опытных инженеров - Роба Пайка, Роберта Гризмера и Кена Томпсона, все они принимали участие в разработке таких значимых проектов, как Unix и его различные компоненты.
Основная цель создания Go заключалась в решении некоторых проблем, которые возникали при разработке программного обеспечения в больших системах, особенно в свете эволюции индустрии к облачным вычислениям, многопоточности и микросервисной архитектуре.
С момента своего первого релиза GoLang быстро набрал популярность среди разработчиков и компаний благодаря своей простоте, производительности и поддержке современных парадигм программирования. В настоящее время он используется во многих крупных проектах и компаниях, включая Google, Docker, Kubernetes и многие другие.
Преимущества перехода на GoLang
Язык программирования Go, предлагает ряд преимуществ перед PHP:
- Производительность: GoLang является компилируемым языком (с возможностью запуска приложений в режиме интерпритатора), что обычно приводит к более быстрому времени исполнения по сравнению с чисто интерпретируемыми языками, такими как PHP. Среда выполнения GoLang также оптимизирована для лучшей производительности и меньшего потребления памяти.
- Поддержка многопоточности: Встроенная поддержка многопоточности в GoLang с помощью горутин облегчает создание высокопроизводительных многопоточных приложений. Поддержка многопоточного программирования в PHP (на момент релиза 8.2), как бы так сказать, слегка ограничена и требует внешних библиотек и/или расширений.
Вот простой пример использования горутин в GoLang:
В этом примере создаются две горутины для параллельной печати сообщений. Это более эффективно, чем использование традиционных потоков или аналогов PHP, таких как pthreads (deprecated) или parallel.
- Простота развертывания: Приложения на GoLang могут быть скомпилированы в один исполняемый файл, что упрощает развертывание. Приложения на PHP часто требуют отдельного веб-сервера и среды выполнения.
- Статическая типизация: GoLang - это статически типизированный язык, который помогает обнаруживать ошибки на ранней стадии разработки и улучшает качество кода. Иными словами, вы просто не сможете даже отладку приложения запустить, если где-то указан неправильный тип данных.
- Безопасность: GoLang старается предотвратить некоторые типичные ошибки программирования, такие как неправильное управление памятью и race conditions, с помощью строгой статической типизации и сборки мусора. Помимо этого, поскольку приложения на Go можно скомпилировать, в случае если злоумышленник как-то проникнет на сервер, он не сможет изменить функционал приложения, добавив зловредов в скрипты.
- Небольшой размер Docker-контейнеров: Приложения на GoLang могут быть упакованы в небольшие Docker-контейнеры, что снижает потребление ресурсов и время запуска.
Dockerfile для PHP-приложения
Dockerfile для GoLang-приложения
В этом примере Dockerfile для PHP требует базового образа php:8.2-apache, который включает в себя Apache, PHP и все зависимости. Dockerfile для GoLang, с другой стороны, использует многостадийную сборку для создания более маленького образа. Но ещё можно скомпилировать GoLang приложение так, чтобы оно могло работать во FROM scratch контейнере.
Про зарплаты
Ещё одно преимущество перехода на GoLang в том, что в среднем специалисты работающие с этим языком программирования получают большую чем PHP-шники зарплату.
По данным статистического исследования "Зарплаты разработчиков в первой половине 2022: языки и квалификации", проведённого Хабр Карьера:
- Среди джунов: самая низкая зарплата в первой половине 2022 года была у PHP-разработчиков — 50 000 ₽. Джуны в С# получали немного больше — 55 000 ₽. Самые высокооплачиваемые джуны — в Go-разработке: они зарабатывали 96 000 ₽.
- Среди мидлов: лидеры по размеру зарплаты — разработчики в Go и Objective-C, они получали 200 000 ₽. Самые низкооплачиваемые специалисты в 1С — 120 000 ₽.
- У сеньоров: зарплаты варьируются от 185 000 ₽ — в 1С, до 300 000 ₽ — в Go, Swift и Objective-С.
- Среди лидов: на первом месте зарплата Swift-разработчиков — 350 000 ₽. Меньше всего зарплата среди лидов у 1С разработчиков — 174 000 ₽.
Кстати, более свежих графиков специалисты из Хабр Карьеры не публиковали, но по текстовому отчёту за второе полугодие 22го средние зарплаты у GoLang программистов выросли на 22%.
Полагаю это связано с большой распространённостью PHP и высокой конкуренцией на рынке труда, низкий порог входа приводит в профессию большое количество молодых PHP программистов, они начинают демпинговать, что в свою очередь приводит к тому, что средняя заработная плата сильно ниже чем в других областях программирования.
Как видите, изучать GoLang будучи PHP-шником не только интересно (потому что это что-то новое), но и полезно для семейного бюджета :)
Несколько полезных советов
В процессе изучения у меня возникал ряд вопросов и вот некоторые моменты которые я для себя отметил, возможно они пригодятся и вам, начните с теории, в частности:
- Изучите синтаксис GoLang и идиоматический код: GoLang имеет другой синтаксис и стиль кода по сравнению с PHP. Потратьте время на изучение языка и ознакомление с его фундаментальными особенностями. Для этого отлично подходит официальная документация.
- Строгая типизация: GoLang имеет строгую статическую систему типов, которая отличается от гибридной динамически-статической типизации PHP (на момент релиза 8.2, возможно в будущем строгая типизация в PHP станет обязательной, а не опциональной). Узнайте о базовых типах данных GoLang, выводе типов и преобразовании типов, а также о том как описывать свои собственные структуры данных.
- Ознакомьтесь со стандартными библиотеками: GoLang имеет большое количество встроенных стандартных библиотек, которые предлагают широкий спектр функциональности. Изучите библиотеки, чтобы узнать о часто используемых пакетах и функциях.
- Начинайте с малого: Практика в паре с теорией помогут вам быстрее разобраться с особенностями языка и закрепить эти знания. Начните с перевода какого-нибудь небольшого PHP-приложения на GoLang, например простенького API клиента или библиотеки которая выполняет какое-нибудь несложное преобразование данных.
Про пакеты GoLang
Теперь хочу рассказать про пожалуй одну из самых моих любимых фич, которые умеет GoLang, а именно пакеты. Пакеты в GoLang играют центральную роль в организации и структурировании кода. Вот несколько ключевых понятий и принципов, которые стоит понимать, когда речь идет о пакетах в Go:
- Пакеты для изоляции кода: Пакеты в Go используются для группировки связанных функций, типов и переменных вместе. Пакет в Go аналогичен модулям или пространствам имен в других языках программирования. Они обеспечивают уровень изоляции, который позволяет вам скрывать детали реализации и предоставлять только необходимые интерфейсы.
- Структура пакетов: В Go каждая папка является пакетом (или может быть пакетом), и каждый файл в этой папке должен объявить тот же пакет в начале файла. Имя пакета обычно соответствует имени папки, которую он представляет, хотя это не обязательно.
- Пакет main: Особый пакет в Go - это пакет main. Этот пакет используется для создания исполняемого файла в Go. Функция main(), объявленная в пакете main, будет точкой входа при выполнении программы.
- Импорт пакетов: Для использования кода из других пакетов в Go, вы должны импортировать эти пакеты. Импорт пакетов происходит с помощью ключевого слова import, после которого указывается строка, представляющая путь к пакету.
- Область видимости: В Go все имена (функций, переменных, типов), начинающиеся с заглавной буквы, являются экспортируемыми - они доступны для импорта из других пакетов. Если имя начинается со строчной буквы, оно не экспортируется и доступно только внутри пакета.
- Стандартная библиотека: Go поставляется со стандартной библиотекой, которая содержит множество полезных пакетов для работы с базовыми типами данных, файловой системой, сетевыми операциями, и т.д. Эти пакеты располагаются в каталоге src вашего рабочего каталога Go (GOPATH).
- Управление зависимостями: В Go есть инструменты для управления зависимостями, такие как go mod, которые автоматически управляют зависимостями вашего проекта. Эти инструменты автоматически скачивают необходимые пакеты, управляют их версиями и обеспечивают изоляцию проекта, создавая приватное пространство для каждого проекта с его собственными зависимостями.
- Пакеты пользователей: Помимо стандартной библиотеки Go и пакетов из вашего собственного проекта, вы можете также использовать пакеты, созданные другими разработчиками. Вы можете найти эти пакеты на различных хостингах пакетов, таких как GitHub, Bitbucket и др.
- Пакет net/http: Это один из самых часто используемых пакетов Go. Он предоставляет функциональность для создания HTTP-серверов и клиентов, обработки HTTP-запросов и ответов, работы с URL и многое другое.
- Тестирование пакетов: Go имеет встроенную поддержку тестирования с помощью пакета testing. Вы можете создавать тестовые случаи прямо в тех же пакетах, где находится ваш код, и запускать их с помощью команды go test.
Ближайший аналог пакетов GoLang в PHP это неймспейсы.
В целом, пакеты в GoLang - это мощный инструмент для структурирования и организации вашего кода. Они обеспечивают уровень изоляции и модульности, который помогает вам создавать более чистый и управляемый код.
Установка GoLang
Мотивацию зачем и почему разобрали, теперь давайте приступим к более детальному разбору как, начнём, как говорится, с начала, а именно с вопросов установки.
Процесс установки GoLang достаточно прост и одинаков для большинства операционных систем. Вот основные шаги, которые вам нужно выполнить, чтобы установить GoLang на ваш компьютер:
Скачивание бинарного пакета GoLang
Перейдите на официальную страницу скачивания Go, где представлены бинарные пакеты для различных операционных систем и платформ. Выберите подходящий для вашей операционной системы и скачайте его.
Установка бинарного пакета GoLang
Откройте скачанный файл и следуйте инструкциям по установке. Процесс установки может немного отличаться в зависимости от вашей операционной системы:
- Windows: Запустите скачанный MSI-файл и следуйте инструкциям установщика.
- macOS: Откройте скачанный файл .pkg и следуйте инструкциям установщика.
- Linux: Распакуйте скачанный архив tar.gz в каталог $HOME/.go. Вы можете сделать это с помощью следующей команды:
mkdir -pv $HOME/.go
wget https://go.dev/dl/go1.20.4.linux-amd64.tar.gz
tar -C $HOME/.go -xfvz go1.20.4.linux-amd64.tar.gz --strip-components=1
Настройка переменных окружения
Данная процедура необходима для всех операционных систем, включая Linux, Windows и macOS. Это позволяет системе знать, где искать исполняемый файл Go, когда вы вводите команду go в терминале.
Вот как вы можете настроить переменные окружения в разных операционных системах:
- Linux/macOS: Вы можете добавить путь к Go в переменную окружения PATH, добавив следующую строку в файл профиля (например, .bashrc, .bash_profile, .zshrc и т.д.):
export PATH=$PATH:$HOME/.go/bin
- Windows: Вы можете добавить путь к Go в переменную окружения PATH через "Системные свойства". Откройте "Системные свойства" -> "Дополнительно" -> "Переменные среды" и в разделе "Системные переменные" найдите переменную PATH и добавьте в конец строки путь к директории bin вашей Go установки, например, C:\Go\bin.
После настройки переменных окружения, обязательно перезапустите терминал, чтобы изменения вступили в силу.
Проверка установки
Откройте новое окно терминала и выполните следующую команду, чтобы проверить, что Go установлен правильно:
go version
Если все было сделано правильно, вы должны увидеть версию Go, которую вы только что установили.
Выбор IDE для разработки на GoLang
Выбор интегрированной среды разработки (IDE) существенно влияет на ваш процесс разработки. Правильная IDE может облегчить написание кода, ускорить отладку и упростить управление проектом. Вот некоторые из лучших IDE, оптимизированных для работы с GoLang:
Visual Studio Code (VSCode) (ссылка)
Это популярный редактор кода, который может быть настроен под Go с помощью Go extension. Расширение Go для VSCode предлагает функции, такие как подсветка синтаксиса, подсказки по коду, автодополнение, отладку и многое другое. Недостаток этой IDE пожалуй только в том, что её делает Microsoft, сами понимаете моё отношение к этой "компании".
GoLand (cсылка)
GoLand от JetBrains является полностью оснащенной IDE, специально разработанной для GoLang. Она предлагает все, что вам может понадобиться для эффективной разработки на Go, включая подсветку синтаксиса, инструменты для рефакторинга, поддержку шаблонов, интегрированный отладчик и поддержку тестирования.
PS. Лично я пользуюсь именно этой IDE
LiteIDE (ссылка)
LiteIDE - это простая и легкая IDE для GoLang. Она предлагает функции, такие как подсветка синтаксиса, поддержка отладки, интеграция с Git и простой в использовании интерфейс.
Atom (ссылка)
Atom - это удобный настраиваемый редактор кода с поддержкой плагинов. Вы можете добавить поддержку Go с помощью плагина go-plus, который предлагает автодополнение, подсветку синтаксиса, отладку и другие функции.
К сожалению GitHub забили на его разработку, поэтому в настоящее время он сопровождается сообществом энтузиастов, хотя сообщество внесло много Pull Request'ов, улучшающих юзабилити, поэтому с некоторой точки зрения Atom даже лучше стал.
Sublime Text (ссылка)
Sublime Text - это мощный редактор кода, который может быть настроен для работы с Go с помощью пакета GoSublime. Этот пакет предлагает функции, включая подсветку синтаксиса, подсказки по коду, поддержку отладки, горячие клавиши и многое другое.
Eclipse (ссылка)
Eclipse - это многоязычная IDE, которая может быть настроена для работы с Go с помощью плагина Goclipse. Плагин предлагает подсветку синтаксиса, поддержку отладки и интеграцию с Git.
Komodo IDE (ссылка)
Komodo IDE поддерживает множество языков, включая Go. Она предлагает функции, включая подсветку синтаксиса, автодополнение, инструменты для рефакторинга и поддержку тестирования.
Сравнение программ на PHP и на Go
Понять отличие PHP от GoLang проще всего на каких-нибудь простых примерах, давайте разберём парочку, первое - будет скрипт для параллельной загрузки ссылок при помощи Guzzle, а второе - реализовывать простой CRUD (без фреймворка) для работы с базой данных.
Асинхронная загрузка ссылок (кравлер)
Представим, что у нас есть некоторое количество ссылок и нам нужно загрузить их HTML, после чего отобразить его на экране, процедуру загрузки в подобных проектах удобнее всего выполнять асинхронно. Управлять количеством одновременных потоков загрузки не будем, просто всё что есть запустим асинхронно и дождёмся завершения.
Вариант на PHP
В этом примере мы будем использовать библиотеку Guzzle HTTP для отправки асинхронных HTTP запросов. Массив URL-адресов представляет собой список ресурсов, с которыми мы хотим взаимодействовать параллельно. Затем мы создаем массив промисов (promises), каждое из которых представляет собой асинхронный запрос.
Для начала создадим директорию crawler-php после чего перейдём в неё и при помощи composer установим Guzzle.
mkdir crawler-php
cd crawler-php
composer require guzzlehttp/guzzle:^7.0
touch main.php
Далее наполним файл main.php со следующим содержимым:
Функция Promise\unwrap($promises) выполняет все промисы параллельно и возвращает результаты в виде ассоциативного массива, где ключи - это URL-адреса, а значения - это объекты ответа HTTP. Затем мы обрабатываем каждый результат и выводим его в консоль.
Чтобы запустить приложение выполним следующую команду:
php main.php
Помимо Guzzle HTTP, существуют и другие библиотеки, такие как ReactPHP и Swoole, которые предлагают более продвинутые функциональные возможности для параллельной обработки HTTP запросов в PHP.
Вариант на GoLang
В этом примере будем использовать стандартную библиотека Go, установка дополнительных пакетов не требуется, просто создаём директорию, инициализируем пакет и пишем следующий код:
mkdir crawler-go
cd crawler-go
go mod init main
touch main.go
Далее наполним файл main.go со следующим содержимым:
Тут мы перебираем список URL-адресов и для каждого URL запускаем новую goroutine с HTTP-запросом. Синхронизация выполнения goroutine осуществляется через sync.WaitGroup. Этот пример демонстрирует одну из ключевых особенностей Go - поддержку простой и эффективной параллельной обработки.
Далее у нас два варианта, можно либо запустить данную программу в режиме интерпритатора:
go run main.go
Либо скомпилировать бинарный файл, после чего запустить его:
go build
./main
Для отладки удобнее всего запускать в режиме скрипта, но для прода лучше собирать готовый бинарный файл.
Простейшее CRUD приложение
Теперь рассмотрим вариант некоего CRUD приложения для взаимодействия с таблицей MySQL под названием products, мы реализуем простейший роутинг и запросы в базу, ответы система будет отдавать в JSON формате.
Ниже будет список curl запросов при помощи которых в дальнейшем можно протестировать работоспособность приложения:
- Все продукты (GET)
curl -i -X GET http://localhost/products - Продукт по id (GET)
curl -i -X GET http://localhost/product/1 - Создание нового продукта (POST)
curl -i -X POST -d "name=NewProduct&price=99.99" http://localhost/products - Обновление продукта (PUT)
curl -i -X PUT -d "name=UpdatedProduct&price=149.99" http://localhost/product/1 - Удаление продукта (DELETE)
curl -i -X DELETE http://localhost/product/1
Вариант на PHP
В данном примере я не буду рассматрировать варианты с использованием фреймворков, ведь мы сравниваем возможности языков программирования. Для взаимодействия с базой будем использовать расширение PDO с поддержкой MySQL, помимо этого предполагается, что у вас уже настроен Apache2 с расширением PHP, либо связка Nginx + PHP-FPM, либо какой-то иной вариант, поэтому заострять внимание на этом не буду.
И так, создадим директорию, перейдём в неё и далее создадим файл index.php.
mkdir crud-php
cd crud-php
touch index.php
Наполним файл index.php следующим содержимым:
Этот пример показывает, как можно реализовать простейший роутинг на основе URL-адреса запроса. В зависимости от запрашиваемого URL-адреса и HTTP-метода, вызываются соответствующие функции для получения данных, которые затем форматируются в формат JSON и отправляются в ответе.
Обратите внимание, что это очень примитивная реализация роутинга. Для полноценного роутинга в большинстве случаев стоит использовать специализированные библиотеки или фреймворки.
Ещё один важный момент в том, что в этом коде нет обработки ошибок или проверки ввода, которые обычно необходимы в реальном приложении.
Вариант на Go
Создадим простейшее CRUD-приложение на Go, которое работает с базой данных MySQL, для этого выполним шаги по инициализации и добавления необходимого плагина.
mkdir crud-go
cd crud-go
go mod init main
go get github.com/go-sql-driver/mysql
touch main.go
Посколько из коробки GoLang не умеет работать с MySQL необходимо добавить специально расширение mysql, с одной стороны это немного неудобно, с другой на PHP надо тоже ставить соответствующее расширение, но не в рамках проекта, а для PHP в целом.
Приложение кажется немного громоздким, но при желании все фукнции можно вынести в другие файлы (в рамках того же пакета) и обращаться к ним, как если бы они были в одном и том же файле.
В этом примере видно, что мы вынесли модель Product в файл model.go, функции работы с базой в файл functions.go, а в файла main.go остались только обработчики (handlers) запросов.
Как видите, ничего сложного нет :)
Заключение
Итак, мы пришли к финалу нашего небольшого путешествия по миру GoLang. Надеюсь, эта статья помогла вам пролить свет на основные аспекты языка Go и показала, как перейти на него с PHP.
Не забывайте подписываться на мой блог, чтобы быть в курсе всех новых публикаций. Я всегда рад видеть ваши комментарии и отзывы. Лайки также мотивируют меня продолжать писать и делиться своими знаниями и опытом.
Если вам интересно узнать больше или обсудить что-то конкретное, присоединяйтесь к моему Telegram-каналу. Там я регулярно делюсь своими мыслями и новостями в области IT, а также отвечаю на ваши вопросы.
К тому же, если вы хотите поддержать мои усилия и вклад в развитие общества знаний, вы можете сделать пожертвование на CloudTips. Ваша поддержка поможет мне продолжать свою работу и делиться новыми открытиями с вами.
Спасибо за то, что провели время со мной, увидимся в следующей публикации! До встречи!