Comments 44
Прекрасная статья для начинающих и подоспела вовремя. Последние выходные мая — лучше не придумаешь, чтобы написать свое первое приложение на Go.
Tornado решает проблему C10K. Автор слишком быстро отбросил Python.
We use Python 3.5, and all servers are single-threaded. Additionally, we use GOMAXPROCS=1 for Go code, nodejs does not use cluster, and all Python servers are single-process.
У Go нет GIL. Когда вы захотите «заюзать» сервер целиком со всеми его ядрами, начнется «балансировщик запросов, разделяемый кэш, ...» и далее по тексту. В Go вам просто не надо будет выставлять GOMAXPROCS=1 и оно «как-то само» по всем ядрам «расползется»…
Я, разумеется, утрирую… но доля истины в моем комментарии есть.
Я пишу и на go и на python так что на мой взгляд такие сравнения вредны своим непрофессиональным подходом.
фреймворк является необязательным и не рекомендуется.
Да, на Golang нет особой необходимости в сложных фреймворках.
Но мне нужна была функциональность middleware для сервиса — я выбрал https://github.com/labstack/echo. Да, можно сделать самому, но зачем?..
Не знаю, насколько верное решение, время покажет.
Спасибо за статью.
Интересно это конечно всё, но отсутствие фреймворков — проблема, причём реальная. SPA — очень спорная часть жизни веба, с одной стороны это конечно хорошо и тихий переход к вебу как к платформе, но именно это же и убивает лёгкость веба. Тогда уж легче и экономнее будет установить нативное приложение, чем хранить в кеше 1000 строк js кода. Так что в этом моменте я бы поспорил, хотя сам очень люблю SPA.
А вот фреймворки реально нужны, в любом случае. И не потому, что яп не спроектирован под веб, а потому, что хочется иметь модульность проекта, лёгкость работы с ним и низкий порог входа в проект. Фреймворки в каком-то смысле создают стандартны написания и комьюнити, а оно в свою очередь профессионалов, с которыми легко работать именно в контексте этого фреймворка. Ведь в какой-то момент команда может поменяться полностью, и мало кто захочет копаться в нативном громоздком коде, написанным какими-то людьми несколько лет назад по каким-то своим правилам.
Для начала, Go не поддерживает объекты — то, что обозначено O в аббревиатуре ORM.
Что вы имели в виду под «Go не поддерживает объекты»?
Вот как это выглядит: https://play.golang.org/p/f5m6WNseR8
Как видно на примере, я определил Animal и его интерфейс, потом создал структуру Cat и Dog. Они приняли в себя структуру Animal анонимно, т.е. утрированно унаследовали поля и методы Animal. Далее проитерировал по слайсу моих домашних питомцев и вызвал методы объектов.
В Go есть ООП, но не такое, как мы привыкли видеть. С другой стороны, никогда не будет сотен слоев абстракций, в которых черт ногу сломит.
Ещё хотелось бы напомнить, что строго определения и стандарта ООП нету.
Скажите, а с какой целью вы в своем примере встраиваете интерфейс IAnimal в структуру Animal? В Go нет надобности как-то объявлять, что структура будет соответствовать какому-либо интерфейсу — если реализовали у структуры все методы интерфейса, значит структура ему соответствует.
Добавлено: и да, в вашем примере нет «анонимных структур» )
Я ответил под вашим постом, потому что многие заявляют как факт: «В Go нету ООП». Окей, пусть сначала принесут сюда стандарт ООП, для начала.
И да, Ruby нигде сейчас не доминирует и даже успел перестать быть мейнстримом.
Этому есть какое-то подтверждение? Я слышал только о добавлении guild http://olivierlacan.com/posts/concurrency-in-ruby-3-with-guilds/, но это совсем не избавление от gil.
Эти программы запускаются как единственный процесс, так что кэширование становится тривиальным, а значит, Memcached или Redis не нужны.
Эмм, а аутентификация и сессии пользователей?
На один сервер запускается один экземпляр веб-приложения в случае Go. Соответственно, сессии пользователей можно хранить в рамках этого же процесса (map, в самом простом случае).
Разумеется, при горизонтальном масштабировании (на несколько серверов) кэш придется вынести за пределы приложения.
А ещё кеширование можно организовать средствами Си и вызывать из Go. Ощущается странная мания внести вообще всё внутрь своего приложения. Перечисленные инструменты разрабатывались под конкретные задачи и справляются с ними хорошо, так зачем делать велосипед? А отказ от фреймворков подразумевает что делать его придётся с нуля. HTTPS тоже сами делать будете?
Ну смотрите: сейчас кто то проникнется вашими идеями, начнёт проект на Go. А потом проект взлетит. А потом внезапно придёт осознание что redis таки нужен. А потом nginx с HTTPS. А потом фоновые задачи тоже неплохо бы вынести отдельно (ну там горизонтальное масштабирование и т.п.). И даже жуткий Puppet (ну или не такой жуткий Ansible). И в итоге все описанные преимущества сойдут на нет. А что имеем в итоге? "Ручной" SQL. Ручное управление сессиями. Да вообще всё ручное. И все детали реализации на поверхности.
Я к тому, что вообще, вы правы, конечно. Но в частности — не совсем. Ведь, до какой-то степени приложение можно масштабировать и вертикально. И в случае Go вам не придется прилагать для этого особых усилий. В случае, например, того же python вам изначально придется делать то, о чем мы говорим (балансер, кэш, фон, ...) — без этого будет грустно смотреть на загрузку сервера.
Возможно, я не прав — все-таки я сейчас больше админ…
Есть такая замечательная штука как Ansible (несправедливо не упомянутая в статье), которая будет делать всё это за вас. А есть ещё не менее прекрасный Docker. Но на самом деле это всё мелочи. Я обязательно прочитаю остальные части (кстати, неплохо бы их осмысленно озаглавить), и тогда уже задам вопросы по существу. И да, не заметил что перевод.
Отсюда вывод: да, можно сделать монолит, который будет в 4 раза быстрее на одной машине, чем вот тот стек, что описан в статье, но расти ему будет некуда.
А еще есть база данных, в которую всегда упирается веб, как его не готовь. Вот тут хорошо описано phgrey: Чек-лист по выживанию сайта.
Пример с гуглом не подходит — создатели Го как раз работают в Гугле, и создавали язык специально чтобы разгрузить свои сервера. И у них это в целом получилось, язык нашел свою нишу и используется в Гугле
Решил написать развёрнутый комментарий. Читал статью с большим интересом, подумал: вдруг она убедит меня в том, что Go нужен? Но по ходу статьи все более становилось похоже что автор убеждает себя. Аргументы, скажем так, несостоятельные. Пройдёмся подробнее.
Многопоточность. GIL — это особенность реализации. Она действительно не позволяет использовать многопоточное программирование, но польза от него в веб-приложениях крайне сомнительная (разве что вам действительно необходимо в рамках одного запроса делать какие-то трудоёмкие и параллелящиеся операции; при этом если используется библиотека типа sklearn или numpy, то там параллелизм будет). Дропбоксовцы пилили свою реализацию питона — "Pyston", и кажется даже без GIL (но это не точно). Она была очень быстрой в бенчмарках, но вот прирост производительности в реальном веб-приложении (ради чего всё и затевалось) оказался неприлично маленьким, в итоге её забросили. Так что не GIL'ом единым. В реальных приложениях всякие UWSGI справляются с задачей превосходно. Кстати, в приведённой статье про C10K перечислены Nginx, Tornado и т.д. как решения данной проблемы. В любом случае, ничего сложного в этом нет.
- Фоновые задачи. Да, без них никуда. И да, их как правило следует писать как часть приложения. Но я не вижу ничего плохого (и даже наоборот) в использовании Celery или Resque (да, с redis в качестве бэкенда).
В этом случае та огромная сложность, введенная в первую очередь для возможности использования популярного скриптового языка [для создания веб-прилолжения], оказывается ненужной.
Что?
Особенно учитывая, что Python или Ruby приносят мало выгоды, когда весь вывод — это JSON.
Ну современные СУБД умеют отдавать JSON (тот же Postgres), зачем вообще нужна прослойка в виде Go? Даёшь веб-приложения на PL/SQL!
- ORM не нужен. Ок… Только не забывайте предохраняться от SQL-инъекций. При миграции деликатно промолчу.
- Фреймворк не нужен. Ок… Только не забывайте предохраняться от XSS, CSRF и т.д.
Другая проблема, общая для фреймворков, это то, что они абстрагируют низкоуровневые механизмы от разработчика так, что со временем они становятся настолько загадочными, что буквально невозможно понять, что у них там на самом деле происходит.
Конечно, лучше когда детали реализации на поверхности. Ну или спрятаны в пакет (особенно бинарный).
То, что начинается с лексического псевдонима для одной строки JavaScript становится слоем в слоях транспайлеров, минимайзеров, поверх хелперов, скрытых где-то в подзависимостях.
Я понимаю что это реверанс в сторону нода, но на клиенте от транспайлинга JS тоже откажемся? Что дальше, нафиг ES6? Вернёмся к ActiveX?
А ещё в статье вообще не описаны недостатки Go. Я сам с ним не знаком, но на мой взгляд это в первую очередь своеобразный синтаксис и ООП (точнее, его отсутствие), вместо которого применяется нечто вроде monkey-патчинга, который с моей точки зрения является особо опасным антипаттерном.
Итог: Я так и не увидел ни одного преимущества Go. Перспектива пилить велосипед на каждый чих меня скорее отталкивает. И всё ради чего? Аргумент "патаму что сложна" меня как то не удовлетворяет.
Я знаю, если вместо того, чтобы пользоваться удобным User.find(:all).filter..., которое обеспечивается чем-то вроде ActiveRecord, писать SQL вручную — это нечто неслыханное в некоторых сообществах, но я все-таки думаю, что такое отношение должно измениться. SQL — прекрасный язык.Хочется пожать автору руку. Много лет назад тренд развития средств разработки почему-то пошел таким образом, чтобы спрятать SQL с глаз долой, обложив сверху разными прослойками (ORM), дающими лишь жалкое подобие возможностей SQL.
Сам около полугода разрабатываю разного рода сервисы и миддлвари на Go. Всё идёт хорошо.
Что нужно на мой взгляд учесть и с чем сам часто сталкивался:
Если разрабатывается весь сайт в виде монолита, вероятность падения всего ресурса из-за сбоя на маленькой страничке возрастает. Я бы посоветовал значимую функциональную составляющую предметной области (комментарии/загрузку файлов) выделить в отдельный сервис и общаться с ним хоть по какому протоколу, какой больше нравится.
Программировать нужно очень аккуратно. Зависающий при каких-то экзотических условиях мутекс или неиспользование оных, а также некорректное использование тикеров обеспечит вам стабильные падения части вашего ресурса. Поэтому нужно очень тщательно всё тестировать и пользоваться go build -race
.
Автоперезапуск упавшей части веб-приложения решается путём создания из них системных сервисов с автоперезапуском при падениях.
А если планируете вести простой блог для себя или сайт-портфолио, то обратите внимание на Hugo, свяжите его с Caddy с плагином http.hugo и наслаждайтесь статическим сайтом, который автоматически генерируется из исходников в виде markdown-страниц
Создание веб-приложения на Go в 2017 году