Бесплатный хостинг Golang: преимущества и недостатки

Плюсы и минусы бесплатного хостинга Golang

Введение

Раньше моих базовых знаний HTML, CSS и JavaScript было достаточно для моих скромных нужд в сайтостроении. Большинство приложений, которые я когда-либо создавал, были сделаны с помощью mod_python, напрямую используя механизм публикации обработчиков (прим.пер.: пример можно посмотреть тут). Забавно, что будучи ранним последователем Python, я также немало поработал с Rails. В течение последних нескольких лет я сосредоточился на инфраструкте (больших) данных, которая вовсе не является веб-разработкой, хотя необходимость в веб-интерфейсах тут — не редкость. Фактически, приложение, которым я сейчас занимаюсь, является приложением для работы с данными, но оно не опенсорсное и то, что оно делает, не имеет значения для данной статьи. В общем, это должно прояснить, с какой стороны я на все это смотрю.

Python и Ruby

Еще год назад я бы рекомендовал Python или Ruby в качестве среды веб-приложения. Может быть есть и другие подобные языки, но с моей точки зрения, в мире доминируют Python и Ruby.

Большую часть времени главной задачей веб-приложения было конструирование веб-страниц с помощью компоновки конечного HTML на стороне сервера. Как Python, так и Ruby очень хорошо подходят для извлечения данных из БД и превращению их в кучу HTML-кода с помощью шаблонов. Существует множество фреймворков/инструментов на выбор, например, Rails, Django, Sinatra, Flask и т.д. и т.п.

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

Работа с Let’s Encrypt

Начальная версия нашего приложения работает по протоколу HTTP, но при возможности всегда рекомендуется использовать протокол HTTPS. К счастью, в Go это не проблема.

Если у вас уже есть сертификат и закрытый ключ, просто используйте , указав корректные пути к файлам сертификата и ключа:

Но можно сделать лучше.

Let’s Encrypt — это удостоверяющий центр, выдающий бесплатные сертификаты с возможностью их автоматического обновления. Для использования этого сервиса в Go-приложениях доступен пакет autocert.

Настроить Let’s Encrypt проще всего используя вспомогательный метод в связке с . Вспомогательный метод получает и обновляет TLS-сертификаты, в то время как HTTP-сервер занимается обработкой запросов:

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

Таким простым способом можно реализовать полную поддержку HTTPS с автоматическим обновлением сертификата.

1: Создание приложения Go

Сначала нужно создать простое веб-приложение «Hello World» на Go. Оно будет работать по домену your_domain, а по your_domain/greet/ оно будет приветствовать пользователей. Если вы хотите узнать больше об основах программирования на Go, ознакомьтесь с нашей статьей Написание простой программы Go.

Сначала создайте в вашем каталоге GOPATH новый каталог для хранения исходного файла. Вы можете назвать папку как угодно, а мы назовем ее go-web:

Если следовать структуре файлов, предложенной в мануале Установка Go и настройка локальной среды разработки в Ubuntu 18.04, у этого каталога будет путь ~/go/go-web.

Затем выполните следующую команду, чтобы вернуться в каталог GOPATH:

Используйте nano или другой текстовый редактор, чтобы создать файл main.go. Он будет содержать исходный код веб-приложения:

Давайте напишем функции приложения Hello World. Для этого добавьте следующий код Go в новый файл main.go:

Теперь давайте рассмотрим данный файл подробнее.

Сначала мы написали точку входа в приложение:

Строка package main говорит компилятору Go скомпилировать этот файл как исполняемую программу, а не как библиотеку.

Далее идут операторы import:

Этот фрагмент импортирует модули, необходимые для работы этого кода, включая стандартный пакет fmt и пакет net/http для веб-сервера.

Следующий фрагмент создает первый маршрут в функции main, которая является точкой входа любого приложения Go:

func main создает родительский маршрут /, который при запросе вернет текст Hello World.

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

При этом URL.Path сохраняет значение, которое идет сразу после /greet/, и передает значение в качестве имени из параметра URL.

Последний фрагмент создает экземпляр сервера:

Он запускает сервер и открывает приложение через порт 9990, используя встроенный http-сервер Go.

Изучив код в файле main.go, сохраните файл и выйдите из текстового редактора.

Затем создайте двоичный исполняемый файл вашего приложения с помощью команды:

Предыдущая команда скомпилирует main.go и создаст исполняемый файл по имени main.

Итак, вы создали тестовое веб-приложение Go. Затем затем мы создадим системный файл systemd, чтобы приложение работало в фоновом режиме даже тогда, когда вы выйдете с сервера.

Обработка HTTP соединения

Сейчас ваш HTTPS сервер работает отлично. Используя StartSSL сертификат вы не будете видеть предупреждения, заходя на ваш сайт https://yourdomain.com.

Но как быть http://yourdomain.com? Так как HTTP сервер теперь не запущен, то страничка не загрузится. Есть два способа решить эту проблему.

Редирект с HTTP на HTTPS

Это наиболее верный подход, если вы хотите заинкриптить весь ваш трафик. Для достижения этого, вам нужна функция, которая будет выполнять редирект с HTTP на HTTPS:

Или, используя два разных для HTTP и HTTPS серверов, вы можете редиректить на HTTPS только по специфическим путям (например /admin/):

И на этом все. Экспериментируйте с HTTPS и Go в удовольствие!

6 апрель 2015

Шаблоны в Go

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

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

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

Импортируйте этот пакет в ваш файл и используйте его следующим образом:

— переменная уровня пакета, которая указывает на определение шаблона из предоставленных файлов. Вызов анализирует файл в корне каталога нашего проекта и проверяет его на валидность.

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

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

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

Остановите запущенный процесс в вашем терминале с помощью Ctrl-C и запустите его снова с помощью , затем обновите ваш браузер. Вы должны увидеть текст «News App Demo» на странице, как показано ниже:

Dependency Injection

С DI пришлось немного помучаться. Сначала выбрал Dig. И сначала все было отлично. Описал сервисы, Dig далее сам строит зависимости, удобно. Но потом оказалось, что сервисы нельзя переопределить, например, при тестировании. Поэтому в итоге пришел к тому, что взял простой сервис контейнер sarulabs/di.

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

Но в итоге, как в случае с Dig, так и в случае с сервис контейнером, пришлось тесты вынести в отдельный пакет. Иначе получается, что тесты запускаются отдельно по пакетам (), но не запускаются сразу для всего приложения (), из-за возникающих при этом циклических зависимостей.

Обертки обработчиков HTTP

Немного поворчу: мне не нравится слово “middleware”. Концепция обертки существует с начала вычислений, поэтому не вижу необходимости изобретать для нее новые слова.

Но отбросим это в сторону, допустим, нам потребовалась аутентификация для определенного URL. Сейчас наш обработчик главной страницы выглядит так:

Мы можем написать функцию, которая принимает в качестве аргумента и возвращает (другой)

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

С учетом этого, регистрация обработчика теперь будет выглядеть так:

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

Практика

Создадим файл /project/consigment.proto.Официальная документация protobuf

Это простой пример, который содержит сервис который вы хотите предоставить другим сервисам: service ShippingService, затем мы определим свои сообщения. Protobuf статически типизированный протокол, и мы можем создавать пользовательские типы (похоже на структуры в golang). Здесь контейнер, вложен в партию.

Установим библиотеки, компилятор и скомпилируем наш протокол:

На выходе должен получиться файл:

Это код, который автоматически генерируется библиотеками gRPC / protobuf, чтобы вы могли связать свое определение protobuf с вашим собственным кодом.

Напишем main.go

Пожалуйста, внимательно прочитайте комментарии, оставленные в коде. Судя по всему, здесь мы создаем логику реализации, в которой наши методы gRPC взаимодействуют, используя сгенерированные форматы, создавая новый сервер gRPC на порту 50051. Теперь там будет жить наш gRPC сервис.
Вы можете запустить это с помощью $ go run main.go, но вы ничего не увидите, и вы не сможете его использовать… Итак, давайте создадим клиента, чтобы увидеть его в действии.

Давайте создадим интерфейс командной строки, который возьмет файл JSON и будет взаимодействовать с нашей службой gRPC.

В корневом каталоге создайте новый подкаталог $ mkdir consignment-cli. В этом каталоге создайте файл cli.go со следующим содержимым:

Теперь создайте партию (consignment-cli / consignment.json):

Теперь, если вы запустите $ go run main.go из пакета seaport, а затем в отдельной панели терминала запустите $ go run cli.go. Вы должны увидеть сообщение «Created: true».
Но как мы можем проверить, что именно было создано? Давайте обновим нашу службу с помощью метода GetConsignments, чтобы мы могли просматривать все наши созданные партии.

Итак, здесь мы создали новый метод на нашем сервисе под названием GetConsignments, мы также создали новый GetRequest, который пока не содержит ничего. Мы также добавили поле отправленных партий в наше ответное сообщение. Вы заметите, что тип здесь имеет ключевое слово repeated до типа. Это, как вы, наверное, догадались, просто означает рассматривать это поле как массив этих типов.

Не спешите запускать программу, реализация наших методов gRPC основана на сопоставлении интерфейса, созданного библиотекой protobuf, нам необходимо убедиться, что наша реализация соответствует нашему proto определению.

Здесь мы включили наш новый метод GetConsignments, обновили наше хранилище и интерфейс, соответственно созданным в определении consignments.proto. Если вы снова запустите $ go run main.go, то программа должно снова заработать.

Давайте обновим наш инструмент cli, чтобы включить возможность вызова этого метода и появилась возможность перечислить наши партии:

Добавим код выше в cli.go и снова запустите $ go run cli.go. Клиент запустит CreateConsignment, а затем вызовет GetConsignments. И вы должны увидеть, что в ответе список содержит состав партии.

Таким образом, у нас есть первый микросервис и клиент, чтобы взаимодействовать с ним, используя protobuf и gRPC.

Следующая часть этой серии будет включать интеграцию go-micro, которая является мощной основой для создания микросервисов на основе gRPC. Мы также создадим наш второй сервис. Рассмотрим работу наших сервисов в контейнерах Docker, в следующей части этой серии статей.

Получение сертификата для сервера и приватного ключа

Использование OpenSSL

Вы можете легко сгенерировать оба файла с помощью OpenSSL. OpenSSL поставляется в Mac OS X и Linux. Если вы используете Windows, то вам нужно установить бинарники отдельно.

К счастью, для генерирование сертификата и приватного ключа с помощью OpenSSL достаточно одной команды:

Вам нужно будет ответить на пару вопросов в момент генерации. Самая важная часть, это поле “Common Name (e.g. server FQDN or YOUR name)”. Тут вы должны указать имя вашего сервера (например myblog.com, или 127.0.0.1:8081 если вам нужен доступ к вашей локальной машине на 8081 порту).

После этого, вы обнаружите два файла “cert.pem” и “key.pem” в той папке, где вы запускали OpenSSL команду. Учтите, что эти файлы называются самоподписанным сертификатом. Это значит, что вы можете использовать эти файлы, но браузер будет определять соединение как не безопасное.

Вы можете сами проверить это, как только запустите сервер

с указанием сгенерированного файла. Перейдя на страничку https://127.0.0.1:8081 в браузере вы увидите предупреждение безопасности.

Это означает, что сертификат на сервере не подписан доверенным центром сертификации. В Firefox мне нужно кликнуть “I Understand the Risks” и после этого браузер перейдет на сайт. В хроме нужно кликнуть “Advanced” и затем так же последует переход на страницу.

Используем Go

Есть другой способ генерации файлов сертификата и ключа – вы можете сделать это непосредственно с помощью Go кода. В стандартной поставке Go есть пример программы, которая демонстрирует как это делается. Она называется generate_cert.go.

Для удобства, я собрал все это в отдельную библиотеку, названную httpscerts. Мы можем модифицировать нашу программу для использования httpscerts и автоматической генерации необходимых сертификатов:

Конечно, ваш браузер все также отобразит предупреждение о самоподписанном сертификате.

Использование StartSSL

Самодписанные сертификаты это удобно для тестирования. Но как только вы запустите сервер в продакшене, вам станет нужен сертификат подписанный в доверенном центре, который будет нормально принимать браузер и операционные системы.

К сожалению, это платная услуга. Для примера, Comodo сдерет с вас $100 за сертификат на 1 год. Internet Security Research Group работает над этой проблемой, но пока нет возможности получить бесплатный сертификат.

Единственная альтернатива, это использовать сервис StartSSL. StartSSL выдает сертификат для одного домена, за который не нужно будет платить в течении первого года. Конечно, вам придется им заплатить за отзыв сертификата, в случае Heartbleed например, но сейчас это единственный вариант получить бесплатный сертификат, хоть и на ограниченное время.

Зарегистрируйтесь на StartSSL и сгенерируйте сертификат и приватный ключ для своего домена. Внимательно прочитайте инструкцию или найдите пару туториалов по использованию StartSSL.

В дальнейшем, будем считать, что вы сохранили сертификат как “cert.pem” и приватный ключ как “key.pem”.

Ваш сертификат может быть защищен паролем. Для этого откройте “key.pem” в обычном текстовом редакторе. Если он действительно зашифрован паролем, то вы увидите что-то вроде:

Чтобы удалить пароли из приватного ключа, используйте OpenSSL команду:

В конце концов, вам нужно добавить StartSSL Intermediate CA и StartSSL Root CA в “cert.pem”

Скачайте “Class 1 Intermediate Server CA” и “StartCom Root CA (PEM encoded)” из StartSSL Tool Box (Log In > Tool Box > StartCom CA Certificates) и положите файлы рядом с вашим “cert.pem”. Используя Linux и Mac OS X, запустите:

Используя Windows, запустите:

Теперь вы можете использовать “cert_combined.pem” и “key_unencrypted.pem” в вашей Go программе. Если хотите, можете переименовать их в “cert.pem” и “key.pem”.

Как работает net/http

В прошлом примере использовался пакет net/http, который служит в Go основным средством для разработки HTTP-клиентов и серверов. Чтобы разобраться в коде, следует кратко объяснить три важные концепции: , и .

HTTP-обработчики

Обработчиком называется то, что принимает запрос и возвращает ответ. В Go обработчики реализуют интерфейс со следующей сигнатурой:

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

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

Таким образом, обработчики формируют ответы на запросы. Но как понять, какой именно обработчик нужно использовать в данный момент?

Маршрутизация запросов

Для выбора обработчика запроса в Go используется HTTP-мультиплексор. В некоторых библиотеках он называется «muxer» или «router», но суть та же. Мультиплексор выбирает обработчик на основе анализа пути запроса.

Если вам нужна продвинутая поддержка маршрутизации, следует обратиться к сторонним библиотекам. Достойные альтернативы — gorilla/mux и go-chi/chi — позволяют простым образом реализовать промежуточную обработку, настроить wildcard-маршрутизацию и решить ряд других задач. Однако важнее то, что они совместимы со стандартными HTTP-обработчиками. Таким образом, сохранится простота кода и возможность его безболезненного изменения в будущем.

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

Обработка запросов

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

Как мы увидим далее, сервер отвечает за всё, что связано с обработкой соединений. В частности, сюда относится работа по протоколу TLS. В нашем примере при вызове используется стандартный HTTP-сервер.

Теперь перейдём к более сложным примерам.

Подключение HTTPS

Если вы хотите использовать зашифрованный протокол https, то вам необходимо использовать функцию ListenAndServeTLS. Рассмотрим пример ее использования.

В этой функции помимо порта и функции-обработчика нужно указать путь к сертификату и к приватному ключу.

Пользователи Mac могут сгенерировать сертификат с помощью утилиты OpenSSL. OpenSSL поставляется в Mac OS X и Linux. Если вы используете Windows, то вам нужно установить бинарники отдельно.

Генерируем сертификат с приватным ключом

Вам нужно будет ответить на несколько вопросов в момент генерации. В поле “Common Name (e.g. server FQDN or YOUR name)” указываем путь к локальному адресу “127.0.0.1:8080”. После генерации в этой папке появятся два файла: cert.pem и key.pem. Учтите, эти файлы называются самоподписным сертификатом, поэтому браузер будет определять соединение как небезопасное.

Итак, приводим весь код в файле main.go

На этом все, мы запустили простейший сервер с примером ответа “Привет!”.

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

Используем пакет net/http для создания сервера

Пакет предоставляет возможности по обработке клиент-серверных запросов.

Откроем ранее созданный файл main.go из предыдущей статьи, который выглядит так:

Чтобы использовать пакет, необходимо его импортировать. Добавим в import название пакета

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

Функция ListenAndServe принимает два параметра — порт соединения и функцию-обработчик, которая будет выполнена при запуске сервера. В нашем случае, она не задана.

Далее необходимо задать обработку роутов – адресов сайта. В нашем примере мы обрабатываем “http://localhost:8080/”, то есть, роут “/”. Когда пользователь вводит адрес “http://localhost:8080/”, вызывается функция sayhello в котором происходит обработка запроса.

Добавим функцию sayhello:

Любая функция-обработчик принимает два параметра:

  1. http.ResponseWriter — это структура которая описывает ответ
  2. *http.Request — указатель на запрос. Из этого параметра можно получать тело запроса, параметры POST, GET или заголовки.

Наша функция передает в ответ “Привет!”

Давайте запустим нашу программу

Компилятор попросит вас подтвердить прослушку порта, поэтому соглашаемся. В браузере вводим “http://localhost:8080/” и видим на странице переданное сообщение.

Motivation

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

  • https://github.com/jmoiron/sqlx
  • https://github.com/go-reform/reform
  • https://github.com/jinzhu/gorm
  • https://github.com/Masterminds/squirrel
  • https://github.com/volatiletech/sqlboiler
  • https://github.com/drone/sqlgen
  • https://github.com/gocraft/dbr
  • https://github.com/go-gorp/gorp
  • https://github.com/doug-martin/goqu
  • https://github.com/src-d/go-kallax
  • https://github.com/go-pg/pg

Когда я переходил несколько лет назад на язык Golang, у меня уже был опыт работы с базами данных на разных языках. С использованием ORM, например ActiveRecord, и без. Пройдя путь от любви до ненависти, не имея проблем с написанием нескольких дополнительных строчек кода, взаимодействие с базой данных в Golang пришло к нечто похожему на repository pattern. Описываем интерфейс работы с базой данных, реализуем с помощью стандартных db.Query, row.Scan. Использовать дополнительные обертки просто не имело смысла, это было непрозрачно, заставляло бы быть на чеку.

Сам язык SQL уже представляет из себя абстракцию между вашей программой и данными в хранилище. Мне всегда казалось нелогичным пытаться описать схему данных, а потом строить сложные запросы. Структура ответа в таком случае отличается от схемы данных. Получается что контракт надо описывать не на уровне схемы данных, а на уровне запроса и ответа. Этот подход в веб разработке мы используем, когда описываем структуры данных запросов и ответов API. При обращении к сервису по RESTful JSON или gRPC, мы декларируем контракт на уровне запроса и ответа с помощью JSON Schema или Protobuf, а не схемы данных сущностей внутри сервисов.

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

Такой способ делает вашу программу предсказуемой. Но будем честны, это не мечта поэта. Мы хотим сократить количество шаблонного кода для составления запроса, наполнения структур данных, использовать связывание переменных и так далее. Я попробовал сформулировать список требований, которым должна удовлетворять желанный набор утилит.

Обновление модулей

По умолчанию, Go не обновляет модули без спроса. “И это хорошо”, поскольку нам всем хотелось бы предсказуемости в наших сборках. Если бы модули Go обновлялись бы автоматически каждый раз, когда выходит новая версия, мы вернулись бы в “тёмные века до-Go1.11”. Но нет, нам надо сообщить Go, чтобы он обновил для нас модули.

А сделаем мы это с помощью нашего старого друга — :

  • запускаем , чтобы использовать последний минорный или патч- релиз (т.е. команда обновит с 1.0.0 до, скажем, 1.0.1 или до 1.1.0, если такая версия доступна)
  • запускаем чтобы использовать последнюю патч-версию (т.е. пакет обновится до 1.0.1, но не до 1.1.0)
  • запускаем , чтобы обновиться до конкретной версии (например, )

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

Поскольку наша программа использовала версию 1.0.0 нашего пакета и мы только что создали версию 1.0.1, любая из следующих команд обновит нас до 1.0.1:

После запуска (допустим, ), наш изменился:

Параметры в URL

В какой-то момент нам могут понадобиться параметры в URL, например, , где — это идентификатор человека. Стандартная библиотека Go ничего для этого не предоставляет, оставляя эту задачу в качестве упражнения для разработчика. Программный компонент, ответственный за такую штуку, называется , т.е. «мультиплексор», или «маршрутизатор», и его можно заменить нестандартной реализацией. Маршрутизатор также реализует метод , что означает, что он удовлетворяет интерфейсу http.Handler, то есть он является обработчиком.

Очень популярным вариантом маршрутизатора является Gorilla Mux. Ему можно делегировать целые пути в тех местах, где требуется больше гибкости. Например, мы можем решить, что все, от и ниже, обрабатывается маршрутизатором Gorilla, и мы хотим, чтобы все это еще было аутентифицировано, тогда это может выглядеть так:

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

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

Отправляем запрос по News API и рендерим результаты

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

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

Сначала объявите новую переменную под переменной :

Затем используйте её в функции следующим образом:

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

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

Убедитесь, что вы добавили пакет в свой импорт, затем перезапустите сервер и передайте требуемый флаг , как показано ниже:

Далее, давайте продолжим и обновим , чтобы поисковый запрос пользователя отправлялся на newsapi.org и результаты отображались в нашем шаблоне.

Замените два вызова метода в конце функции следующим кодом:

Сначала мы создаем новый экземпляр структуры и устанавливаем значение поля равным значению параметра URL в HTTP-запросе.

После этого мы конвертируем переменную в целое число и присваиваем результат полю переменной . Затем мы создаем переменную и устанавливаем ее значение равным 20. Эта переменная представляет количество результатов, которые API новостей будет возвращать в своем ответе. Это значение может находиться в диапазоне от 0 до 100.

Затем мы создаем конечную точку с помощью и делаем запрос GET к ней. Если ответ от News API не , мы вернем клиенту общую ошибку сервера. В противном случае тело ответа парсится в .

Затем мы вычисляем общее количество страниц путем деления поля на . Например, если запрос возвращает 100 результатов, а мы одновременно просматриваем только 20, нам нужно будет пролистать пять страниц, чтобы просмотреть все 100 результатов по этому запросу.

После этого мы рендерим наш шаблон и передаем переменную в качестве интерфейса данных. Это позволяет нам получать доступ к данным из объекта JSON в нашем шаблоне, как вы увидите.

Прежде чем перейти к , обязательно обновите ваши импорты, как показано ниже:

Давайте продолжим и отобразим результаты на странице, изменив файл следующим образом. Добавьте это под тегом :

Чтобы получить доступ к полю структуры в шаблоне, мы используем оператор точки. Этот оператор ссылается на объект структуры (в данном случае ), а затем внутри шаблона мы просто указываем имя поля (как ).

Блок позволяет нам перебирать слайс в Go и выводить некоторый HTML для каждого элемента в слайсе. Здесь мы перебираем слайс структур , содержащихся в поле , и выводим HTML на каждой итерации.

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

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Добавить комментарий