Недавно Digital Ocean объявила о выходе на рынок PaaS со своей новой платформой приложений. Они размещали виртуальные машины (дроплеты) и сервисы на основе Kubernetes в течение многих лет, но теперь они создают платформу, которая представляет собой простой пункт и щелчок, чтобы запустить приложение.

В этом уроке мы собираемся создать приложение на этой платформе. Я буду использовать Go для создания небольшого веб-API, который будет поддерживаться базой данных SQLite. Я покажу вам необходимые шаги, и мы увидим, насколько легко (или нет) развертывать приложения на платформе.

Мы создадим небольшой сервис, который:

  • Принимает название города в качестве входных данных
  • Поиск по базе данных
  • Возвращает почтовый индекс и другую информацию для этого города

Если вы хотите следовать этому руководству, вот что вам понадобится:

Создание вашего репозитория

Первое, что нам нужно сделать, это создать репозиторий на GitHub. Платформа приложений Digital Ocean использует ваши репозитории для извлечения кода и сборки оттуда.

Теперь клонируйте репозиторий образцов Digital Ocean в другую папку:

git clone https://github.com/digitalocean/sample-golang.git

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

git clone https://github.com/JeremyMorgan/GoZipCodeDigitalOcean.git
cp -r /sample-golang/* /GoZipCodeDigitalOcean

Теперь у меня есть пример кода в моем собственном репо:

Круто, теперь давайте отправим это на Github.

git add .
git commmit -m "Initial Commit"
git push origin main

Теперь пример проекта доступен на моем Github, где я могу к нему подключиться.

Настройка приложения Digital Ocean

Перейдите на https://cloud.digitalocean.com/apps

И нажмите «Запустить приложение».

Затем вы подключите свой Github к Digital Ocean.

Вы можете дать ему разрешение на все ваши репозитории или только на определенные (рекомендуется).

Затем создайте свое приложение и ветку, из которой вы хотите выполнить развертывание. Я выбираю «основной» в моем случае.

Здесь вы можете выбрать, следует ли автоматически развертывать изменения кода. Нажмите "Далее.

На следующем экране вы можете настроить некоторые вещи. Убедитесь, что Go обнаружен, и настройте его как веб-службу.

Здесь вы можете добавить базу данных, но мы пропустим это и нажмем «Далее».

Затем вы выберете план. Статические сайты бесплатны, а сервисы Go — нет, поэтому здесь я выбрал план за 5 долларов. Этого достаточно для проверки концепции и сайтов разработки.

Как только вы нажмете «Далее», ваш сайт начнет развертываться автоматически.

И мы встали! Давайте проверим это.

Тестирование демо-сайта

Теперь наш демонстрационный сайт запущен и работает, но на нем особо не на что смотреть:

Вы можете использовать что-то вроде Postman, чтобы проверить свои маршруты:

Маршруты в примере приложения:

  • /
  • /кэш
  • /заголовки
  • /env
  • /статус

Итак, мы готовы идти. Давайте превратим это в настоящее приложение.

Создание нового метода

Прежде всего, мы создадим новый метод для добавления в наше приложение. Он добавит новый маршрут «/zip» для поиска почтового индекса и другой информации о городе. Наш URL будет выглядеть как

https://(ourURL)/zip?city="(город, который мы ищем)"

Итак, мы создадим новый метод:

http.HandleFunc("/zip", func(w http.ResponseWriter, r *http.Request) {
}

Мы уточним это позже в уроке.

Создание базы данных

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

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

Я собираюсь создать здесь базу данных с почтовыми индексами и информацией о городе, связанной с ней. Для этого проекта я скачал персональную версию этой базы данных почтовых индексов (CSV).

Единственное, что я сделал, это изменил названия столбцов:

Вы можете назвать их как угодно.

Далее мы будем использовать Браузер БД для SQLite. Вы можете запустить это в Windows, Mac или Linux.

Сначала мы создадим новую базу данных:

И сохраните его как zipcode.db.

Теперь нам нужно импортировать наш CSV в новую базу данных.

Перейдите в Файл -> Импорт -> Таблица из файла CSV.

Убедитесь, что ваш разделитель и кавычки установлены, и вы должны увидеть это:

Завершите импорт и нажмите «Записать изменения», чтобы сохранить изменения в базе данных.

Теперь у нас есть наша база данных.

Создание нашего результата

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

Вот информация, которую я решил вернуть, когда вы запрашиваете город. Я буду выводить это в JSON.

Давайте создадим структуру, которая выглядит следующим образом:

type city struct {
	Zip        string `json:"zip"`
	City       string `json:"city"`
	State      string `json:"state"`
	County     string `json:"county"`
	Timezone   string `json:"timezone"`
	Latitude   string `json:"latitude"`
	Longitude  string `json:"longitude"`
	Population string `json:"population"`
}

Обратите внимание, как в каждом из них я добавил:

`json:"zip"`

Эта нотация позволяет вам указать, как должно выглядеть выходное имя JSON. Таким образом, мы можем сделать все строчными или даже полностью изменить имя, если захотим.

Это будет наш выход. Давайте заполним его!

Создание нашего ZIP-метода

Имейте в виду, что это демонстрационное приложение. Не то, что вы бы использовали в производстве. Мы собираемся создать этот метод, чтобы инкапсулировать функциональность «город в почтовый индекс». Этот метод будет:

  • Принять ввод строки для названия города
  • Подключиться к базе данных SQLite
  • Запустите запрос к нему
  • Соберите результаты
  • Собери их в коллекцию
  • Кодировать их в JSON
  • Верни это

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

Импорт

Нам нужно добавить несколько пакетов, чтобы это работало. Добавьте следующее в оператор импорта:

"database/sql"
"encoding/json"
"log"
_ "github.com/mattn/go-sqlite3"

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

Переменные

Добавьте эти два объявления переменных в начало метода:

// get the city from the URL
reqCity, ok := r.URL.Query()["city"]
// Collection of cities
var cities []city

Первая переменная, reqCity, — это город, который мы ищем, и мы получим его из URL-адреса.

Следующий — cities — представляет собой набор городов. Это связано с тем, что часто бывает несколько городов с одинаковым названием, а крупные имеют несколько почтовых индексов:

Поэтому мы сохраним их в коллекции и вернем.

Подключиться к базе данных

Далее мы хотим подключиться к нашей базе данных SQLite:

// open up database
db, err := sql.Open("sqlite3", "./zipcode.db")
if err != nil {
  log.Fatal(err)
}
defer db.Close()

Это довольно простое соединение. Мы используем библиотеку SQLite, чтобы открыть zipcode.db. Если его не существует или есть проблема, мы закроем программу. Мы также хотим отложить database.Close(), поэтому мы закрываем соединение, когда метод завершен.

Запросить базу данных

Далее мы запустим наш запрос к базе данных. Первое, что мы хотим сделать, это удалить кавычки из строки в нашем URL:

searchCity := strings.Trim(reqCity[0], "\"")

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

Далее мы запустим запрос:

rows, err := db.Query("select zip, primaryCity, state, county, timezone, latitude, longitude, irsEstimatedPopulation2015 from zip_code_database where primaryCity like '%" + searchCity + "%' and type = 'STANDARD'")
if err != nil {
  log.Fatal(err)
}

Здесь мы запускаем оператор select для базы данных и возвращаем его в rows. Это позволит нам работать с данными после их возврата.

Давайте также отложим rows.Close():

defer rows.Close()

Сладкий! Теперь у нас (надеюсь) есть некоторые данные, с которыми мы можем работать.

Разбор результата

Теперь у нас есть результирующий набор, давайте воспользуемся циклом for для его разбора:

for rows.Next() {
    city := city{}
    err = rows.Scan(&city.Zip, &city.City, &city.State, &city.County, &city.Timezone, &city.Latitude, &city.Longitude, &city.Population)
    cities = append(cities, city)
    if err != nil {
	log.Fatal(err)
    }
}

Здесь мы создаем новый экземпляр структуры city и используем строки. Scan для сканирования каждой строки и извлечения элементов для размещения в нашей структуре. Если с этим будет ошибка, мы сломаем программу.

Затем мы добавим каждый найденный город в коллекцию городов. В идеале у нас будут чистые данные.

Добавим немного обработки ошибок (опять же, просто дамп приложения).

err = rows.Err()
if err != nil {
  log.Fatal(err)
}

А у нас хорошо!

Упаковка и отправка данных

Мы упакуем это и отправим.

if ok && len(cities) > 0 {
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(cities)
} else {
    w.WriteHeader(404)
}

Помните, как мы взяли значение из URL-адреса и вернули его ok? Мы сейчас это проверяем. Так что если был запрошенный город, и мы получили результат, то будем двигаться дальше.

Мы устанавливаем заголовок content-type в application/JSON, а затем кодируем нашу коллекцию городов как JSON. И это то, что будет возвращено.

Если в нашем запросе или результате есть ошибка, мы просто вернем 404. Давайте попробуем!

Отправьте приложение в Digital Ocean

Чтобы развернуть это приложение в Digital Ocean, нам просто нужно зафиксировать и отправить:

git add .
git commit -m "Creating our First Deploy"
git push origin main

И он начнет развертывание.

Как только он соберется (надеюсь, так оно и будет), вы увидите следующее:

Отобразится URL-адрес вашего приложения. Итак, давайте быстро проверим это:

И это работает! Я ввожу свой родной город (Гастон), и он возвращает мой почтовый индекс и другую информацию о городе, которую я указал!

Вы также можете использовать Postman, чтобы проверить это:

И это работает! Есть также несколько интересных идей, если бы это было реальное приложение:

Мои мысли об этой платформе

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

Что я уже заметил в Digital Ocean:

  • Его легко использовать
  • Не требуется клиентское программное обеспечение (только Git!)
  • Укажи и щелкни простотой
  • Возможность настройки, когда вам нужно

В целом, у этой платформы есть большой потенциал. Так что отправляйтесь в Цифровой океан и попробуйте. Я думаю, вам понравится!

Вопросы, комментарии? Дайте мне знать!