Golang — Вызываем Cthulhu с помощью JavaScript

Привет! Сегодня я решил вызвать Cthulhu с помощью парсинга JavaScript на таком замечательном языке, как Golang.

Cthulhu golang

Итак, идёт 2017 год, а поэтому мы обязаны заниматься не чем-то полезным, а тем, что вызовет хайп. Не даром, сейчас все крупные компании разрабатывают по новейшей методологиии — HDD (Hype Driven Development).

Что же сейчас горячо? Ну, наверное, семь-восемь — это golang, docker, kubernetes, terraform, prometheus, MongoDB. Сегодня, пожалуй, остановимся только на языке Го, и о моём супер кратком опыте его использования.

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

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

  1. https://golang.org/doc/code.html — базовая информация про язык.
  2. https://tour.golang.org/welcome/1 — REPL GO с простыми примерами и их объяснениями.
  3. https://golang.org/doc/effective_go.html — большая статья, описывающая ключевые моменты языка, их реализацию, best practices.
  4. https://gobyexample.com/ — примеры кода на Go с пояснениями и возможностью запуска в Лайве.
  5. https://www.quora.com/What-are-the-best-online-resources-for-learning-Go-programming-language — тут тоже какие-то ссылки читал, уже не помню, что.

В общем, синтаксически язык действительно довольно простой. Самая сложная часть — это правильная и корректаня работа с горутинами и всем, что связано с конкурентностью. Например, можно в default блоке select делать что-то тяжёлое, напрочь убив производительность event loop.

Другая относительно сложная часть языка, на которую многие жалуются — это слайсы. Но, думаю, если вы знаете, как устроен Динамический массив внутри (например, ArrayList из Java, или List из C#, или vector в С++), то для вас тут не будет ничего сложного. Да и исходники открыты, а ещё — по всем сложным вещам языка есть отличные статьи — https://habrahabr.ru/post/202948/.

После чтения базовой литературы, а также изучения реализации некоторых вещей в языке, я решил что-нибудь написать на Go. К сожалению, я слаб на идеи (был бы силён, нахер бы я вёл блок о программирование, а не занимался бы стартапом?). Поэтому, выбрал самое банальное (кстати, если вы знаете что-то крутое, что хотелось бы написать на go — очереди, планировщики, базы, сервера, прокси, компиляторы, gc — я глубоко открыт к предложениям и готов быть бесплатной рабочей силой).

Итак, задача — распарсить API одного сайта и предоставить полученные данные внешним клиентам по HTTP API. Тут есть 4 банальных подзадачи:

  1. Получить HTML и JS внешнего сайта по ссылке.
  2. Распарсить HTML и JS, получив нужные credentials. Попутно тут мы призовём Cthulhu с помощью регулярок.
  3. Авторизовавшись по не своим креденшелам, получить JSON и распарсить его, преобразовав в нужные данные.
  4. Отдать нужные данные каким-то внешним потребителям по HTTP.

Используемые тулы

  • GoLand — слава богам, лучшая компания всех времён и народов уже выпустила IDE для Go. Да, это альфа-бета (на самом деле, EAP). Да, это пока сырой продукт. Да, при работе я несколько раз словил неотловленные Exceptions. Но этим действительно можно пользовать. Да и лучше просто нет. Как и в любом другом языке, GoLand — это про Cutting Edge.
  • Dependency manager — … блять… Ну, как же так. Языку уже 8 лет, он создавался во времена maven и gradle, а до сих пор ничего нехера нет.

    Встроенное go get подойдёт разве что пет проджектам с количеством зависимостей, стремящимся к нулю (ещё бы, нет даже способа зафиксировать версию).

    dep — официальное новое средство управлением зависимостями, которое только находится в разработке, пока даже не production ready. Когда-нибудь, наверное, будет крутым.

    glide — если кратко — подделка от рубистов для рубистов. Всё так и пахнет этим языком. Субьективно не понравилось, не надо, спасибо. (бля, почему всё, что делают рубисты, получается каким-то не таким, как надо? редмайн, например, или CoffeeScript).

  • Command go — отличная консольная команда. Её вы будете использовать постоянно. С помощью команды go, я, как минимум, собирал проект, а также запустал тесты для него.

Some Thoughts on Golang

  1. Про standard library. Std крайне хороша. В ней вы найдете, плюс минус, всё, что вы только можете ожидать от стандартной либы. К слову, я свой проектик написал с zero external dependencies. Конечно же, тут нужно поставить большую звездочку (прямо, как в том ипотечном договоре, который вы подписали прошлым летом). HTTP сервер есть, но он не highload oriented. Парсер JSON есть, но с супер бедными возможностями. HTTP роутер есть, но опять-таки с нулём сахара. Другими словами, всё будет как-то работать, но не идеально, и в продакшене вы, конечно же, выбирите какие-то альтернативные либы для этих вещей.

    Отдельно нужно сказать про goroutines. Они реализованы, не как библиотека (реверанс в сторону Котлина, в котором Корутины — это просто Либа), а как часть языка. Причём сделано действительно очень качественно.

  2. Про компилятор. Во-первых, он довольно быстрый, действительно. Например, в Скале даже не маленьком проекте вы успете сбегать в Бразилию, собрать незрелые зёрна кофе, привезти их в Москву, разторможить, высушить на горячих полях Ростова, привести к себе в Сибирь и сделать напиток богов.

    Кроме того, вы сразу заметите, что компилятор Go крайне придирчив. Не удалил неиспользуемый импорт? ПНХ. Не сделал явный каст от числа в строку? Правильно, ПНХ. Не подставил скобку в if-е (ну, это не компилятор, конечно, а спека, которую компилятор реализует) — ПНХ.

  3. Про Конкурентность. Это одна из двух sales point языка. Действительно, легковестные потоки, плюс event loop делают конкурентную разработку на этом языке — крайне приятной и относительно (например, c++ или джавы) — простой. Вы плюс-минус пишите линейный код, почти не заботясь о примитивах синхронизации и гонках (из-за отсутствия разделяемых ресурсов и общения через каналы). Всё это как-то само работает (рантайм Go переключает горутины в то время, когда горутина засыпает на каком-то блокирующем вызове). Вам просто нужно выделять горутины под каждый чих, и как-то суммарно супервайзить это дело. Одним словом, красота.

  4. Про Fat jar. Ну, почти Jar, а на самом деле — бинарник. Go статически линукует все зависимости. На выходе вы получаете от компилятора один исполняемый файл, который можно просто just run. А ещё можно кроскомпилить это дело, например, собирая бинарник на винде под линукс. Это, собствено, второй сейлс поинт, за который все полюбили язык.

  5. Про Простоту. Думаю, что все из вас слышали, что Golang — простой язык, что его learning curve — это функция f(x) = x. В целом, так и есть. В языке мало сложных синтаксических конструкций. Почти всё уже было в C/C++. Это и хорошо, и плохо. Так, например, если вы хотите попарсить JSON, то вы будете страдать, шаг за шагом разбирая входящий объект на map-ы и interface{}. Ну, или вам прийдётся для каждого объекта создавать структуру без какой-либо кодогенерации.
  6. Выводы

    Стоит ли попробовать этот язык? Однозначно да. Ведь крайне много людей считает, что это будущая замена Java, а нам с вами нужна строка в резюме. Да и в Го есть интересные идеи, с которыми полезно познакомится (зеленые потоки и каналы, например).

    Надо ли тащить язык в продакшн вместо Джавы или C#? Не думаю, что вы получите от этого какие-то профиты, особенно, если вы не пишите микросервисы из 1000 строк. Всё-таки, у языка есть ряд родовых травм, которые обещают пофиксить во второй версии языка. Примеры таких вещей — Обработка ошибок (в примере выше, где я паршу json, видна вся тупость отсутствия исключений, которые мы по факту эмулируем сами, руками) и Дженерики.

    Будем надеяться, что у этого языка всё будет хорошо. Не так уж и много успешных продуктов выходит из под крыла Гугла.

    Категории: О жизни