Go с точки зрения PHP программиста

Автор оригинала: Sobit Akhmedov
  • Перевод
Предлагаю вашему вниманию перевод статьи Go from PHP engineer's perspective с сайта sobit.me.

Будучи PHP программистом, задумывались ли вы об идее изучения других языков программирования?

Уже много лет выбор многих компаний падает на PHP для создания полноценных монолитных приложений. Более того, за последние 5 лет фреймворки (Symfony, Laravel, Zend), инструменты (Composer, Monolog) и стремительно растущее сообщество (PHP-FIG) помогли многим разработчикам в создании программного обеспечения на уровне предприятий. Многие компании, такие как Facebook, Yahoo!, Wikipedia, Wordpress, Tumblr, начинали свою историю с PHP, и это не помешало им стать успешными в последующие годы.

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

В этой статье мы попытаемся понять, как далеко мы сможем зайти, имея в арсенале только PHP, и где может вступить Go, чтобы помочь решить проблемы, с которыми нам предстоит столкнуться.

PHP и микросервисы


Каждый PHP разработчик знает, что, если ему удастся довести время инициализации большого монолитного приложения до 30мс, это отличный результат! Добавить к этому 50-100мс для обработки самого запроса, и перед нами поразительное общее время ответа.

Так как мы планируем разбить наш монолит, что произойдет, если мы решим придерживаться подобной архитектуры и для наших сервисов? Простые вычисления, и мы уже тратим 300мс только на инициализацию, если сервисы обратились друг к другу 10 раз в течение единого запроса. Неприятный пользовательский опыт!

В то время, как PHP сияет в мире веб-разработки, его возможности в микросервисных архитектурах еще не созрели. Естественные термины — такие как обработка времени ожидания, проверки здоровья, сбор метрик, прерыватели — зачастую незнакомы PHP программисту. Многие из них можно найти в различных фреймворках во многих других языках прямо из коробки. Поддержка же их в экосистеме PHP слишком мала, если присутствует вообще.

Встречайте Go


Из Википедии:

Go (часто также Golang) — компилируемый, многопоточный язык программирования, разработанный компанией Google. Первоначальная разработка Go началась в сентябре 2007 года, а его непосредственным проектированием занимались Роберт Гризмер, Роб Пайк и Кен Томпсон занимавшиеся до этого проектом разработки операционной системы Inferno. Официально язык был представлен в ноябре 2009 года.

Go был разработан в Google. Он не был веселым 20%-ным проектом, также он не был предназначен добиться чего-то, недоступного другим. Его создали всего лишь из-за разочарования от сложности, которую создавали очень большие команды, работая над очень большими частями приложения на языках с большим набором возможностей.

Несмотря на такие замечательные черты, как легкий параллелизм или быстрая компиляция, основная черта, делающая язык особенным, — это невероятная простота. К слову, количество ключевых слов в Go — 25, в то время, как в PHP их насчитывается 67.

Go появился примерно в то же время, когда PHP получил поддержку пространства имен (2009). Спустя лишь 6 лет на нем созданы дюжины великолепных проектов, среди прочих Docker, Kubernetes, etcd, InfluxDB. Множество компаний, таких как Cloudflare, Google, Dropbox, SoundCloud, Twitter, PayPal, доверяют ему при написании своих бэкенд систем.

Возвращаясь к микросервисам


Давайте пройдемся по тем проблемам, о которых мы недавно говорили, и попытаемся понять, чего же мы можем добиться с использованием Go.

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

Традиционный "Hello, World!" API укладывается в 10 строк кода и отвечает быстрее миллисекунды. Возможности использования всех ядер процессора позволяет разработчикам параллельно запускать сложные части приложения. Экосистема позволяет выбрать любой транспортный протокол, например JSON по HTTP, gRPC, Protocol Buffers или Thrift. Запросы легко прослеживаются в Zipkin. Метрики экспортируются в различные бэкенды, от statsd до Prometheus. Есть возможность ограничить пропускную способность запросов с помощью ограничителей и защитить общение клиент-сервис с помощью прерывателей.

Больше о Go


Язык


Go — язык сильной типизации, что заставляет указывать тип переменной при ее объявлении:

var name string = "sobit"

Переменные могут определять тип по присваемому значению. Код выше аналогичен упрощенной версии:

var name = "sobit"

// или еще проще:

name := "sobit"

Теперь давайте вспомним, как мы меняем значения двух переменных в PHP:

<?php

$buffer = $first;
$first = $second;
$second = $buffer;

И эквивалент в Go:

first, second = second, first

Это возможно, благодаря множественным возвращаемым значениям. Пример с функцией:

func getName() (string, string) {
    return "sobit", "akhmedov"
}

first, last = getName()

В Go коде вы не найдете привычных foreach, while и do-while. Они объединены в единый оператор for:

// foreach ($bookings as $key => $booking) {}
for key, booking := range bookings {}

// for ($i = 0; $i < count($bookings); $i++) {}
for i := 0; i < len(bookings); i++ {}

// while ($i < count($bookings)) {}
for i < len(bookings) {}

// do {} while (true);
for {}

Несмотря на то, что в Go нет так называемых "классов" или "объектов", в нем присутствует тип переменной, который соответствует тому же определению, где структура данных объединяет код и поведение. В Go это называется "структурой". Проиллюстрируем на примере:

type rect struct { // объявляем структуру
    width  int
    height int
}

func (r *rect) area() int { // объявляем функцию структуры
    return r.width * r.height
}

r := rect{width: 10, height: 15} // инициализация
fmt.Print(r.area())

Иногда бывает полезным создавать и сложные структуры. Например:

type Employee struct {
    Name string
    Job  Job
}

type Job struct {
    Employer string
    Position string
}

// и инициализиция
e := Employee{
    Name: "Sobit",
    Job: {
        Employer: "GetYourGuide",
        Position: "Software Engineer",
    },
}

Есть множество других особенностей, о которых мне бы хотелось рассказать, но это было бы дублированием отличного документа Effective Go с официального веб-сайта и нескончаемой статьей. Но я хочу воспользоваться моментом и представить вам параллельность в Go, которая, на мой взгляд, является одной из самых интересных тем об этом языке. Перед тем, как мы начнем, вы должны знать две вещи о параллельности в Go — горутины и каналы.

Горутина имеет простую модель: это функция, выполняемая параллельно с другими горутинами в едином адресном пространстве. Когда вызов завершается, горутина тихо выходит. Простейший пример — создать функцию сердцебиения, которая выводит на экран сообщение "Я жив" каждую секунду:

func heartbeat() {
    for {
        time.Sleep(time.Second)
        fmt.Println("I'm still running...")
    }
}

Как нам теперь запустить ее в фоновом режиме, чтобы при этом иметь возможность продолжать выполнять другие задачи? Ответ проще, чем вы могли себе представить, просто добавьте префикс go:

go heartbeat()

// keep doing other stuff

Такой подход сравним с инициацией событий в стиле "запусти-и-забудь". Но что, если нам не нужно "забывать", и мы заинтересованы в результате выполнения функции? Именно в этом случае на помощь приходят каналы:

func getName(id int, c chan string) {
    c <- someHeavyOperationToFindTheName(id)
}

func main() {
    c := make(chan string, 2) // выделить канал

    go getName(1, c) // запустить
    go getName(2, c) // запустить снова, не дожидаясь

    // продолжить выполнение других задач

    fmt.Printf("Employees: %s, %s", <-c, <-c) // объединить
}

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

Инструменты


Go был спроектирован, повторюсь, с простотой в уме. Авторы предприняли радикальный подход к решению повседневных действий разработчиков. Попрощайтесь с бесконечными спорами "таб или пробел" и стандартами программирования от групп сообщества, которые пытаются хоть как-то облегчить обмен кодом. Go содержит в себе инструмент go fmt, который берет на себя ответственность за стиль вашего кода. Не нужно больше посылать друг другу файлы конфигураций IDE, не нужно пытаться запомнить, надо ли ставить открывающую скобку на той же строке или следующей.

Документацию библиотеки можно прочитать с помощью go doc, в то время, как go vet поможет найти потенциальные проблемы в коде. Установка сторонник библиотек происходит простой командой go get github.com/[vendor]/[package], а тесты запускаются с помощью go test [package]. Как видите, большинство инструментов, включаемые разработчиками в каждое приложение в каждом языке, уже тут, прямо из коробки.

Развертка


Развертка приложения — необходимое действие и не зависит от языка программирования и того, что пишут с его помощью. Будучи PHP программистом, сколько Capistrano или Envoy конфигураций вы написали за свою профессиональную карьеру? Сколько файлов, измененных вручную, вам приходилось переносить на хостинг-провайдеры во времена FTP?

Вот так выглядит наиболее распространенная и простая развертка PHP приложения:

  • Выгрузить последний код на целевой сервер в новую папку релиза
  • Скопировать закэшированные зависимости и установить измененные
  • Скопировать конфигурационные файлы среды
  • Запустить все скрипты для разогрева приложения
  • Направить ссылку текущего релиза на новую папку релиза
  • Перезапустить PHP-FPM

Некоторые команды используют более продвинутый подход:

  • Выгрузить последний код на сервер создания билдов
  • Создать "билд" (установить зависимости, разогреть кэши, и т.д.)
  • Создать дистрибутивный "артефакт" (архивированный tar.gz файл)
  • Перенести артефакт на целевой сервер
  • Разархивировать в новую папку релиза
  • Направить ссылку текущего релиза на новую папку релиза
  • Перезапустить PHP-FPM

Конечно, помимо этого, вам надо убедиться, что на целевом и сервере создания билдов установлены хотя бы PHP-FPM и PHP, и лучше бы им совпадать по версиям как между собой, так и с версией, что разработчики используют локально.

А теперь поговорим о процессе развертки Go приложения:

  • Выгрузить последний код на сервер создания билдов
  • Создать билд (заметьте отсутствие кавычек)
  • Перенести артефакт (снова без кавычек) на целевой сервер
  • Перезапустить запущенное приложение

И все. Единственная разница между потенциально простой и продвинутой версией заключается в том, есть ли для этой задачи автономный сервер или нет.

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

Вывод


Никто никогда не рекомендовал разбивать систему на микросервисы до того, как она созреет достаточно для этого. Будучи небольшим, бизнес должен оставаться гибким и быстро реагировать на удобные случаи на рынке. Это — не идеальная среда для создания микросервисов, и можно получить больше пользы от монолитного приложения. В этом случае PHP с его экосистемой идеально подходит под эту стратегию.

Когда организация стабилизируется и в ней становится легко чертить границы ее контекстов, строить микросервисы на PHP для их поддержки может быть болезненным делом. Существуют разные инструменты и техники во многих других языках в помощь этой архитектуре. Вы рискуете тем, что либо создадите свои собственные инструменты, либо вовсе откажетесь от них — оба варианта могут дорого обойтись вашей организации.

С другой стороны, создание микросервисов на Go стоит рассмотрения. Язык прост для написания и понимания. Кривая обучения не настолько крута, как в случае Java или Scala, а производительность не сильно отстает от C. Время компиляции помогает разработчикам оставаться эффективными, в то время, как поддержка многоядерных и сетевых машин позволяет создавать мощные приложения.

Дополнительные материалы


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

Если этого недостаточно, есть также собрание инициатив сообщества, чтобы помочь отточить полученные навыки.

Если вы любите IDE от JetBrains так же, как и я, стоит посмотреть в сторону плагина Go для IntelliJ, который был создан в основном теми же JetBrains разработчиками. Он может быть установлен почти на любую из их IDE, включая PhpStorm. Для других IDE и текстовых редакторов стоит посетить вики страницу.

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

Менее значимое — это возможность создавать клиентские JavaScript приложения с помощью GopherJS, а также полностью нативные или SDK приложения для iOS и Android.
Поделиться публикацией

Комментарии 122

    +1
    Сначала подумал что о Кате..
      +7
      Go — это язык в котором простоту довели до примитивизма. В итоге решения часто начинают распухать на пустом месте т.к. средств языка просто не хватает, на то чтобы все это завернуть красиво.

      В этом отношении даже http://nim-lang.org/ куда более удобный, правда когда пишешь на Nim не покидает чувство, что они дергали разные концепции не имея чуткого понимания того, что хотят получить, но когда пытаешься писать на Go создается впечатление, что целью было создать не простой, а именно обрезанный язык.
        +8
        целью было создать не простой, а именно обрезанный язык.

        Благо это быстро проходит. Писать серверный код на Go одно удовольствие
          0
          Я видимо что-то делаю не так, ибо ничего не распухает. Но если бы пытался все делать, как привык в php или C++, то наверное так и выходило бы.
            0
            Зато если удалось "все это завернуть красиво" можно рассчитывать что и работать будет быстрее. Напротив в Haskell, Skala можно быть почти уверенным — чем элегантней код, тем он медленней.
            –10
            Да, в статье чего то не хватает… Кати?
              +4
              Промт
                –1
                В обе стороны?
                +8
                Согласен с выводами, но мне кажется тема "с точки зрения PHP программиста" не совсем раскрыта.

                Когда садишься писать на Go после PHP, а особенно Symfony, думаешь о Layers, Abstractions, Interfaces, продумываешь архитектуру и заботишься о том, как этот код будет поддерживаться в дальнейшем, и в большинстве случаев… упираешься в простоту Go и приходиться опять искать другую реализацию архитектуры. В итоге главное принять и поверить — что очевидное и самое простое решение — в Go будет самым правильным, и не надо пытаться вот тут вот сделать интерфейс, а вот тут вот убрать повторение кода, чтобы следовать DRY. Мне показалось что Go диктует простую архитектуру, проблемы поддержки которой решаются именно немонолитностью кода, и после возможностей PHP в плане ООП как решения проблем монолита в это трудно поверить :)

                И я бы не сказал что это минус, в выводах очень правильная мысль — PHP вначале, и когда дозрели — выносить в Go.

                PS. Насчет времени инициализации и т.п., http://symfony.com/blog/new-in-symfony-2-8-symfony-as-a-microframework
                  0
                  Насчет времени инициализации всё равно 11ms. Тут скорее надо давать ссылку на http://reactphp.org/.
                    +2
                    Я бы не стал никому рекомендовать использовать ReactPHP в продакшн-системах. Удачный эксперимент, показывающий возможности PHP, не более.
                      +5
                      А можете подробнее рассказать о причинах? Есть опыт успешного внедрения у нас в компании, у других пользователей( Fesor точно)
                      Разрабатываем backend'ы для мобильных приложений\игр, относительный highload, rpm 200k-500k.

                      Помимо ReaсtPHP — есть Icicle, c "coroutines" на генераторах.

                      Также есть проект http://amphp.org/ ориентированный на PHP7. Много интересного "из коробки".
                      И старый добрый, правда очень монолитный phpDaemon
                        –4
                        На мой взгляд, ReactPHP — это не более, чем попытка доказать, что в PHP можно делать вещи в стиле JavaScript / Node.js. В то время, как 95% всех зависимостей из npm дополняют экосистему Node.js, в PHP это — в точности до наоборот. Редкие фреймворки и библиотеки для PHP спроектированы для асинхронного программирования.

                        В конце концов, почему бы просто не использовать Node.js для подобных задач? Взять хотя бы его поддержку сообществом https://github.com/nodejs/node по сравнению с https://github.com/reactphp/react.
                          +6
                          У нас ReactPHP успешно работает в продакшене. Да и зачем использовать node.js, если есть %language%
                            +5
                            На мой взгляд, ReactPHP — это не более, чем попытка доказать, что в PHP можно делать вещи в стиле JavaScript / Node.js.

                            А Node.js это попытка доказать, что Javascript подходит для создания сайтов в стиле PHP. На мой взгляд.
                            Нет, давайте без вентилятора.

                            Редкие фреймворки и библиотеки для PHP спроектированы для асинхронного программирования.

                            Любой фреймворк, который представляет абстракцию на Request\Response отлично работает, не знаю, чтобы кто-то щас делал новые фреймворки по-другому, PSR этому способствует.

                            Мы используем redis и cassandra — для всего есть async экстеншны. Драйвер для mysql с очень давних времен поддерживает async, лет 5
                            Еще можно такой список посмотреть https://github.com/elazar/asynchronous-php
                              +2
                              Хорошая подборка. Спасибо, просветили!
                              0
                              ReactPHP это попытка реализации паттерна "реактор" на PHP, и более чем успешная. И распространения это не получает особо именно из-за консервативных взглядов в духе "php должен умирать".

                              У меня один из проектов крутится на reactphp уже больше года в продакшене, и небыло никаких проблем (а те что были не связаны именно с reactphp а больше с тем, как изначально разработчики использовали монгу и завязали все на синхронные API).

                              Основная проблема PHP — отсутствие вменяемой библиотеки асинхронных/неблокируемых функций. Благо проект amphp как раз таки эту проблему рашета, а за счет корутин можно не волноваться по поводу наступления callback hell. Неблокируемый код в синхронном стиле.

                              Однако я все же предпочитаю для подобных задач использовать node.js, просто потому что мне лень пилить велосипеды, а для PHP их надо написать еще много (неблокируемых). Есть еще надежда на то что в PHP8 появится async/await. А может и раньше.
                        +2
                        думаешь о Layers, Abstractions, Interfaces, продумываешь архитектуру и заботишься о том, как этот код будет поддерживаться в дальнейшем, и в большинстве случаев… упираешься в простоту Go и приходиться опять искать другую реализацию архитектуры

                        Потому что layers, abstraction, interfaces — средства решения задачи, а нечто самое, сущее. Просто в ряде языков, том же Java это — необходимость. Если решать задачу изначально с оглядкой на язык, все получается так же удобно, красиво и поддерживаемо. Парадигма другая, задачи решаются те же.

                        и не надо пытаться вот тут вот сделать интерфейс, а вот тут вот убрать повторение кода, чтобы следовать DRY

                        Потому что иногда это (интерфейсы, ООПизация) становится просто процессом ради процесса.
                        +14
                        Теперь давайте вспомним, как мы меняем значения двух переменных в PHP:

                        $a = 1;
                        $b = 2;
                        list($a, $b) = [$b, $a];
                          –3
                          Это был пример на множественное присваивание, если что. Понятно, что через передачу указателей в функцию можно хоть и десять значений свапнуть.
                            +3
                            list в PHP это не функция, а языковая конструкция
                              0
                              Согласен, php уже давно не использовал, подзабыл. Но смысла это не отменяет. Автор хотел показать, что в go можно делать так:

                              var1, var2, var3 := true, "text", 10

                              или так:

                              var1, var2, var3 := myFunc()

                              Что подставить на второй половине, не имеет значения. Автор использовал для примера смену двух значений. И будь в php коде это list, пример был бы неочевиден.
                                0
                                Согласитесь, что это синтаксический сахар. Так же можно найти какой-нибудь сахар в PHP, которого нет в Go
                                  –1
                                  Прозвучало так, как будто я восхвалял golang. А вы меня осадили.
                                  Множественное присваивание, как и множественные возвращаемые значения из функций это особенность языка, которую стоило описать в статье. Если будет статья, php глазами гофера, то там стоит упомянуть, что в php такого присваивания нет. Но зато есть что-то другое.
                                    +2
                                    Это сахар, т.к. по факту в PHP тоже можно вернуть несколько значений из функции объединив их в массив, а с помощью list их распаковать. Получается немного больше кода, но копирует 1 в 1 возможность go.
                                      0
                                      По сути все языки высокого уровня это сахар, все то же можно было написать и на асме.
                                        0
                                        Зато эффективность этого кода несравнимая. Не надо сравнивать совершенно разные вещи. Это не просто сахар, а конструкция языка, что позволяет не костыли городить, как вы предлагаете в php, а делать все эффективно и прозрачно.
                                          +2
                                          list и array конструкции языка PHP, все прозрачно и эффективно.
                                            +1
                                            Это конструкции для массивов, а не для возвращения нескольких значений из функции. Возвращая массив мы возвращаем массив, одно значение, да еще с нехилым оверхедом. Это не прозрачно и не эффективно. Это костыль для решения проблемы, с которой язык не умеет справляться сам.
                                      +1
                                      Это всего лишь одна из возможностей языка, которая может показаться интересной PHP программисту.
                                      +2
                                      Автор хотел показать, что это именно отличие Go от PHP. И в этом он ошибся. Если бы он хотел просто показать множественное присваивание в Go, то про PHP там бы ничего написано не было, так же как в разделах про переменные, циклы и структуры.

                                      В PHP тоже можно делать так, как вы написали в обоих примерах. По факту отличие только в том, что в Go определена операция "запятая", которая создает… Хм, что же она создает, уж не список ли разнотипных значений, который в PHP называется массивом?

                                      И что подставить на второй половине значение все-таки имеет. В Go нельзя слева написать 2 переменных, справа 3, в PHP можно.
                                        +1
                                        Вполне можно

                                        a, _, b = b, c, a

                                        И ничего запятая не создает, это просто разделитель между разными переменными.
                                          +2
                                          Никаких операций и созданий чего-либо в Go не происходит. Это компилируемый строго типизированный язык. Компилятор знает всю информацию о том, что, какого типа и в каком количестве возвращает функция, что позволяет скомпилировать это без всяких вспомогательных конструкций. У нас уже и так есть стек для этого.

                                          И таки это совсем не тоже самое, что массивы в PHP.
                                            0
                                            Ок, пожалуй, насчет запятой я не прав. Список значений на стеке можно назвать массивом как в C++ или Asm, но не как в PHP.
                                        0
                                        удалено
                                          0
                                          Подобно array(), это не функция, а языковая конструкция. list() используется для того, чтобы присвоить списку переменных значения за одну операцию.
                                            0
                                            Хотя при этом в разделе "Функции PHP > Функции для работы с массивами". Немного сбивает с толку.
                                      +1
                                      И вас не смущает идея создания массива ради экономии двух строк? К слову.
                                        –1
                                        А вас не смущает, что несколько возвращаемых значений сами по себе создают такой массив?) Кстати, не подскажете аналогичную ссылку для Go, как это происходит на низком уровне и сколько памяти занимает?
                                          0
                                          Нет, не создает. Это просто разные переменные.
                                            +4
                                            Можно посмотреть в ассемблере — невероятно, но несколько возвращаемых значений передаются через стек. Никаких массивов там не создается.
                                            +1
                                            Если честно то не очень. Никого же не смущает использование фреймворка с сотнями классов (десятки из которых инстанциируются во время запроса) для простого вывода HTML в браузер.
                                              +1
                                              Кстати, чисто ради интереса проверил результат на PHP 5.6 и PHP 7.0:

                                              5.6

                                              echo memory_get_usage() - $startMemory, ' bytes';
                                              // 14649168 bytes

                                              7.0:

                                              echo memory_get_usage() - $startMemory, ' bytes';
                                              // 4198640 bytes
                                                0
                                                Это не сильно меняет суть проблемы.
                                                  0
                                                  Есть ещё много простора для оптимизации. Я здесь привёл цифры со словами, что ситуация уже стала лучше.
                                            +8
                                            Простите за иронию, но...

                                            Вау, чуваки! Зацените! Тут есть крестообразная отвертка и крест для свершения публичной казни! И то, и другое — крестообразное, так что очень просто перейти от одного к другому!

                                            Ну ведь правда же "похожий" синтаксис (похожий тем, что и там, и сям есть фигурные скобки и синтаксический сахар) — это мелкая деталь на фоне двух замечательных, но совсем-совсем-совсем разных языков программирования?
                                              +3
                                              Крестообразной отверткой можно совершать казнь ничуть не хуже.
                                              –2
                                              Как по мне после пхп проще и логичнее всего переходить на джаву, а не на го. Тем более на горизонте котлин.
                                                +5
                                                Как по мне — не стоит переходить с РНР, а достаточно учить и осваивать новые языки и писать на них. Зачем с чего-то куда-то переходить?
                                                У нас сейчас проект с миллионом строк кода на РНР, зачем мне переходить на что-то другое, тратить год всей команды, а то и больше, чтобы перейти на что-то другое, которое как-бы лучше? Да и наш шеф то не одобрит такое…
                                                Я уже молчу о том, что при этом будет +N багов, к уже имеющимся…
                                                О миграции уже работающих серверах я вообще молчу...
                                                  +2
                                                  Я лишь хотел обратить внимание что по синтаксису джава ближе всего к пхп чем к примеру го. Переходить не переходить это вопрос лично каждого. Я сам лично пишу на трех языках и ничего нормально.
                                                    +1
                                                    На самом деле, большинство багов отсеется на этапе "оно не компилится, ошибка в строке N", так-как компилятор довольно строгий и вероятность скрытых багов гораздо меньше, чем в php или js. В go сами средства языка практически не дают возможности сделать шаг влево-вправо и, я бы сказал, навязывает единый стиль кода и программирования. Я конечно больше сравниваю с nodejs, с которой работаю последние несколько лет. Но и с php тоже знаком не по наслышке.
                                                      0
                                                      Я имел ввиду логические ошибки. Т.к. новы язык и идеально не знаешь, что именно получишь от какой-то конструкции, к примеру.
                                                        0
                                                        Я просто приведу маленький пример. Новичек в php экспериментирует, с таким выражением:

                                                        if ($my_var) { /* .... */ }

                                                        Как поведет себя блок, когда в переменной будет true, 1, "1", "", " ", "string", (10 > "11") и т.д?

                                                        Тот же новичек попробует все подобные варианты в go. Тут он быстро поймет, что скомпилится только первый. Все остальные выдадут ошибку на этапе компиляции. Потому-что go принимает все прямолинейно, только булевы значения. Вот пару примеров, можно нажать и посмотреть ошибки:

                                                        https://play.golang.org/p/t_MDQBvIj1
                                                        https://play.golang.org/p/SCumk_DuV9
                                                        https://play.golang.org/p/DuGHIcdmIq

                                                        Или такой вариант:

                                                        if($test) 
                                                            echo "Ok";
                                                            echo "Test passed!";

                                                        Gо же вообще не позволяет выполнять if, for и т.д. без фигурных скобочек.
                                                        И такой подход практически во всем. Не скажу, что там вообще нет подводных камней, на которые может напороться новичек. Но все гораздо лучше в плане надежности ПО, сужу по реальному опыту применения.
                                                    –3
                                                    А о том, что найти специалистов на РНР куда проще, чем на GO, ну в Одессе уж точно.
                                                    Хотя и по РНР сейчас найти опытных не удаётся...
                                                      +1
                                                      Думаю это ошибочная мысль, ибо количество носителей языка, не свидетельствует о их профессионализме, тем более если это касается таких языков с низким порогом вхождения как php.
                                                        –1
                                                        Да, Вы можете так считать, но я не своё мнение высказал, о озвучил, как оно есть сейчас в Одессе.
                                                          +5
                                                          Ну те кто минусуют, если вы из Одессы, рады будем вашему резюме, присылайте и приходите на собеседование.
                                                            0
                                                            Есть простой способ получить неплохого разработчика на Go — берем опытного человека на php и даем ему небольшой проект на Go. Делать он его будет раза в 3 дольше (в первый раз), но в конце уже будет неплохо знать Go.
                                                            Желательно, конечно, чтобы проект для Go подходит лучше, чем для php.

                                                            Учитывая возраст и распространенность языка, такой путь будет проще и быстрее, чем ждать у моря погоды, пока появятся люди, что уже его изучили и готовы менять работу.
                                                              +1
                                                              Возможно, не стану отрицать, я его ещё не смотрел, но если у нас появился опытный разработчик на РНР, чем "перековывать" его в неплохого на GO, я лучше его отправлю в команду с проектом на РНР.

                                                              • опытный РНРшник получает тоже достаточно хорошо, и менять позицию, просто так, не думаю, что ему это будет сильно интересно. Или нужно предлагать гораздо лучшие условия.
                                                                +1
                                                                Бодишопом веет от такого подхода;)
                                                      0
                                                      Не вижу смысла переходить с PHP на Java.
                                                      Поделитесь, зачем это нужно.

                                                      Кроме того в рамках класса задач, в которых применяется Go, этот переход точно будет бессмысленным.
                                                        +1
                                                        А с Java на PHP — как на это смотрите?
                                                          +3
                                                          Удивительно, но тот же Ebay, считает, что имеет смысл. Так сейчас они переводят свой раздел по продаже авто в в итальянской версии Ebay с Java на РНР.
                                                            +1
                                                            Это интересно! Погуглил, но не нашел эту историю. У Вас есть ссылка?
                                                              0
                                                              Нет, ссылки нет. Знаю от друга, к ним, в крупную фирму, зашёл этот проект, вот он и делился информацией.
                                                            0
                                                            Я перебрался. Для веба J2EE в 2006--2008 был тяжеловат в плане количества телодвижений.
                                                            –3
                                                            Да вы правы, в этом нет никакого смысла вообще. Все большие проекты с хорошими бюджетами в основном на пхп написаны. Да и по производительности ему нет равных в принципе. Очень много качественных библиотек написано студентами для пхп. А особенно радует адекватность и техничексий уровень специалистов, которые пишут на пхп — общаться с ними одно удовольствие. Это все подтверждается огромных количеством пхп вакансий на рынке Европы и Америки.
                                                              +3
                                                              обожаю ничем необоснованные суждения
                                                                +2
                                                                Вы ответили слишком категорично, я ответил в таком же духе. У пхп своя ниша — ненагруженные проекты и админки. Я до сих пор считаю симфони вторую одним из лучших фреймворков для быстрой разработки бекенд админок. Но если глянуть шире…

                                                                1) В хайлоаде пхп проигрывает… да уже почти всем. nodejs, java, erlang, даже питон со своим GIL и то выигрывает
                                                                2) Ентерпрайз — java, с#
                                                                3) Обработка больших данных — java (привет хадуп), R, python
                                                                4) Алгоритмы искусственного обучения — опять таки java, python, c++
                                                                5) Разработка мобильных приложений — java (андроид), objective-c, swift (ios), ну и с трудом С++ (привет QT)
                                                                6) Десктоп — ну там все понятно
                                                                7) Микросервисы — опять java, привет GO (о чем статья), node возможно еще что-то. Тут еще пхп может посоперничать (если нагрузка не велика)
                                                                  +2
                                                                  А сарказм?
                                                            –5
                                                            Статья не так уж и плоха, но ...

                                                            А теперь поговорим о процессе развертки Go приложения:

                                                            А как же магия GOPATH? Даже тот же PHP скачал, поставил, запустил — работает. А в go нужно настраивать GOPATH :(
                                                              0
                                                              Серьезно? Подход Go как раз в том, что на GOPATH все и ограничивается. Дальше все просто работает, одной командой в консоли. Редкий компилируемый язык так может.
                                                                +7
                                                                Ничего себе, нужно иметь научную степень, наверное, чтобы прописать переменную окружения.
                                                                  0
                                                                  А как же локальный вэб-сервер поднимать, что бы заработал php? Я думаю это совокупно GOPATH.
                                                                +2
                                                                Нубский вопрос про деплой Go веб-приложения на Windows. Начал изучать язык, собрал exe простейшего приложения на Gin, залил его на виндовс сервер, через рдп запустил, на IIS настроил reverse proxy на порт приложения. Все вроде бы хорошо, но хочу залить обновление, а процесс приложения не дает перезаписать exe через ftp. Есть ли какие-то общепринятые методы деплоя, желательно без ручного вмешательства в остановку-запуск приложения. И существует ли что-то вроде Node.js-ного Forever, рестартующего веб-апп в случае вылетания по эксепшну?
                                                                  +6
                                                                  Каждый PHP разработчик знает, что, если ему удасться довести время инициализации большого монолитного приложения до 30мс, это отличный результат! Добавить к этому 50-100мс для обработки самого запроса, и перед нами поразительное общее время ответа.

                                                                  Symfony2, nginx+php-fpm, простой запрос — время ответа 20-30мс. И это на тяжёлом фрэймворке с кучей зависимостей и библиотек.
                                                                  Golang, библиотека gin, CRUD на БД, время ответа от без нагрузки на БД — 1-10мс. Разница существенна. Но не критична. Если на php убрать обвязку из Symfony, то разница ещё больше сократится.

                                                                  Развертка приложения — необходимое действие и не зависит от языка программирования и того, что пишут с его помощью. Будучи PHP программистом, сколько Capistrano или Envoy конфигураций вы написали за свою профессиональную карьеру? Сколько файлов, измененных вручную, вам приходилось переносить на хостинг-провайдеры во времена FTP?

                                                                  Далее приводиться огромный список шагов, который не отражает действительность. Первичная настройка капистрано — 5 минут. Деплой — одна консольная команда. Go тут не предоставляет ничего нового, процесс нисколько не отличается. Тот же самый перенос исполняемого файла и конфигов на сервер. И для этих целей я использую тот же самый капистрано. Только для Go появляется предварительный этап — компиляция с нужными флагами.

                                                                  Складывается впечатление, что автор не знаком с php. Бесспорно, golang эффективнее чем php для написания микросервисов, но статья вводит в заблуждения относительно не эффективности php.
                                                                  Сейчас в своей работе я использую связку ruby + golang. На обоих языках написано несколько "микросервисов". Основное выявленное преимущество Go — более низкое потребление памяти и боле эффективная работа с внешними асинхронными запросами.
                                                                    0
                                                                    В разделе про публикацию PHP приложений последним пунктом идёт "Перезапустить PHP-FPM" — зачем? Выкладываем новые исходники и они просто работают! Причём текущие запросы не будут сброшены. А с go приложением, получается, при перезапуске процесса мы можем потерять запросы которые были где-то в середине процесса обработки! Или есть способ zero-downtime перезапуска go приложения?
                                                                      +2
                                                                      Можно же перезапуск устроить так, что он не будет отстреливать всё, а дожидаться завершения последнего запроса. Как nginx c reload
                                                                        0
                                                                        Можно, только graceful shutdown писать руками придётся...
                                                                        +1
                                                                        Graceful shutdown + load balancer + несколько инстансов приложения, обновляемых по очереди. Вот вам и zero downtime.

                                                                        Это нормальная практика для всех приложений, будь то go, python, java и прочее, что висит как процесс
                                                                          0
                                                                          Руками придётся писать же, не?
                                                                            0
                                                                            Все зависит от того, что используете. В finagle на scala есть graceful shutdown из коробки. Наверняка есть готовые решения для множества платформ
                                                                              0
                                                                              Для Go не было.
                                                                                0
                                                                                Из коробки нет, но есть множество пакетов, типа https://github.com/facebookgo/grace
                                                                                  0
                                                                                  Рекомендуете именно этот?
                                                                                    0
                                                                                    Порекомендовать не могу, так-как сам не использую.
                                                                                    Вообще, есть еще варианты, например простой пакет https://github.com/tj/go-gracefully от авторов известного фреймворка express для nodejs
                                                                          +2
                                                                          При наличии OPcache или APC, новые изменения не будут "просто работать".

                                                                          $ php5-fpm reload

                                                                          Команда очистит кэш и принудит его пересоздание при первом обращении.

                                                                          В случае Go приложения, если есть несколько образцов приложения, проблем возникнуть не должно (как пояснил ImLiar). С одним же образцом можно запустить новую версию на соседний порт, перенаправить запросы с веб-сервера на него, и отключить старый после короткого ожидания.
                                                                            0
                                                                            Не будут работать только если время жизни кеша бесконечно. И даже в этом случае перезапускать не обязательно. Что APC что OpCache можно вычистить без перезапуска.
                                                                              0
                                                                              И это создаёт ситуацию, когда запрос может обрабатывать неконсистентный код: часть из кэша старой версии, часть из фс новой версии.
                                                                                0
                                                                                Может и создаёт, да.
                                                                          0
                                                                          Не могу согласиться, что только в памяти дело. У меня зачастую время ответа скрипта на golang — микросекунды, миллисекунды — при сколько-либо существенной нагрузке.

                                                                          Синтетика конечно, но все же
                                                                          image
                                                                            +1
                                                                            Если время ответа CRUD сервиса на Go составляет 10мс, я бы занялся поиском причин.

                                                                            Далее приводиться огромный список шагов, который не отражает действительность. Первичная настройка капистрано — 5 минут. Деплой — одна консольная команда.

                                                                            А разве то, что делает эта консольная команда, — не тот же самый "огромный список шагов"?
                                                                              +1
                                                                              Если время ответа CRUD сервиса на Go составляет 10мс, я бы занялся поиском причин.

                                                                              Причина — время ответа от БД, и тут без разницы, golang, php, python, ruby. На php время ответа будет в пределах 50мс, что конкретно в моём случае не критично.

                                                                              А разве то, что делает эта консольная команда, — не тот же самый «огромный список шагов»?

                                                                              Тот же самый. Там может быть хоть 100 шагов. Можно и golang приложение каждый раз компилировать, переносить на сервер и вручную перезапускать. А можно воспользоваться готовыми инструментами, которые всё сделают сами. И под php\python\ruby эти инструменты сейчас заточены гораздо лучше.
                                                                                0
                                                                                В PHP (классическом с умиранием) соединение с БД делается каждый раз, если не используется persistent connect (в котором много подводных камней). В Go соединение делается один раз и далее повторно используется.
                                                                                  0
                                                                                  И при этом в Go значительно проще организовать кеширование, фильтр Блума, hyperLogLog и многие другие вещи, которые помогают вообще не делать запросы в базу при каждом обращении.
                                                                                    0
                                                                                    Факт. С другой стороны, при наличии нескольких инстансов фронта это всё усложняет приложение неимоверно, хоть и даёт отличную производительность.
                                                                                      0
                                                                                      Это тоже правда, все зависит от архитектуры конкретного приложения. Как пример, недавно была задача банального инкремента на нескольких инстансах, решение было тоже банально, инкремент на накопленное значение из каждого инстанса n раз в секунду. Если бы в том же случае осуществлялась прямая запись, нагрузка на базу была бы критичной на существующих мощностях, и думаю даже на значительно больших.
                                                                                    0
                                                                                    Даже все хитрее. В Go sql.DB это не соединение, а пул, который сам создает, переиспользует и убивает соединения до базы.
                                                                                      0
                                                                                      в котором много подводных камней

                                                                                      На самом деле эти "подводные камни" заключаются лишь в том, что бы люди убирали за собой, а не надеялись что PHP волшебным образом отменит незавершенные транзакции и т.д. Ну то есть та же проблема, по которой понадобились сборщики мусора, или та проблема, из-за которой среднему php-нику нельзя давать работать с тредами или "не умирающим пыхом". Возьмут ребята какой-нибудь react/amphp, впихнут туда доктрину синхронную, и потом кричат направа налево, что PHP не подходит для реализации эффективных решений.

                                                                                      Реализовать небольшую оберточку поверх PHP, которая по завершению запроса будет "невилировать" сайд эффекты текущего запроса, это как бы не сложно.
                                                                                        0
                                                                                        Это не "лишь". Это серьёзно :)
                                                                                +4
                                                                                Многие компании, такие как Facebook, Yahoo!, Wikipedia, Wordpress, Tumblr, начинали свою историю с PHP

                                                                                Yahoo! в этом списке вероятно по ошибке. Yahoo! на несколько лет старше, чем PHP.
                                                                                  0
                                                                                  «Многие компании, такие как Facebook, Yahoo!, Wikipedia, Wordpress, Tumblr, начинали свою историю с PHP»
                                                                                  Альтернатив просто не было. А те что были были еще хуже.
                                                                                    +1
                                                                                    Да ладно, Java уже была...
                                                                                      –2
                                                                                      Java хуже параллелится...
                                                                                        0
                                                                                        Иногда лучше молчать… У явы очень разумное concurrency и качественная memory model (jmm, собственно).
                                                                                          0
                                                                                          Иногда лучше молчать…

                                                                                          Это верно.
                                                                                          О чем я говорю, и о чем вы, вообще не в тему...
                                                                                          0
                                                                                          Не хуже, но немного сложнее.
                                                                                      +2
                                                                                      замечательные черты, как легкий параллелизм

                                                                                      вы должны знать две вещи о параллельности в Go — горутины и каналы.

                                                                                      Горутина имеет простую модель: это функция, выполняемая параллельно с другими горутинами в едином адресном пространстве.

                                                                                      Чувак ни фига не понял.
                                                                                        0
                                                                                        Честное замечание. Я пытался найти более подходящий перевод для "concurrency". Обновлю статью, если посоветуете.
                                                                                          0
                                                                                          Так это перевод такой? Я думал в оригинале parallelism.
                                                                                          Конкурентность.
                                                                                            +1
                                                                                            перевод с его собственного блога. можно ли назвать переводом..? =)
                                                                                              +1
                                                                                              К сожалению, несмотря на то, что русский — мой родной язык, вся профессиональная жизнь проходит на английском. Пусть это прозвучит смешно, но я действительно со словарем переводил многие незнакомые мне на русском языке термины.
                                                                                            0
                                                                                            Одновременность?
                                                                                          –2
                                                                                          Интересные и удобные конструкции, но новичкам лучше с него на начинать. Иначе новички не поймут, что собственно упрощалось и объединялось, и почему можно по другому.
                                                                                            –5
                                                                                            Перевод нормальный ребята, прочитал понял суть вроде не Перельман :) Собит молодчик хорошая статья. Привет из 2шанбе :)
                                                                                              +1
                                                                                              Друзья, поясните пожалуйста, а что произойдет, если someHeavyOperationToFindTheName не успеет заполнить "c" до момента ее использования? Как понять заполнила ли она "c" или нет? Есть событие?
                                                                                                +2
                                                                                                Строчка fmt.Printf("Employees: %s, %s", <-c, <-c)

                                                                                                сначала будет вычислять аргументы в таком порядке: "Employees: %s, %s", <-c, <-c. То есть для вывода на экран значений она сначала вытащит два значения из канала. Если в канале значений нет, то "<-" будет ждать их появления.

                                                                                                чтобы не ждать, можно делать, например, так:

                                                                                                select {
                                                                                                case str := <-c:
                                                                                                     // значение было в канале и мы его вытащили в str
                                                                                                default:
                                                                                                     // канал еще пуст
                                                                                                }
                                                                                                  0
                                                                                                  Спасибо! Какой забавный язык :)
                                                                                                    0
                                                                                                    Был тот же вопрос, спасибо за ответ!

                                                                                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                                                Самое читаемое