Создание службы RESTful API в Go без повторяющихся шаблонов
6 марта 2023 г.Есть много материалов о том, как писать сервисы, где сначала нужно выбрать какой-то фреймворк для использования, потом идет разводка обработчиков, конфигов, логов, хранилища и т.д., не говоря уже о том, чтобы где-то развернуть этот сервис. Мы пишем сервисы уже довольно давно, и чаще всего вы просто хотели пропустить весь этот утомительный процесс склейки вещей и просто написать какой-нибудь полезный код.
Вот почему мы создали инструмент под названием Mify — это генератор шаблонов инфраструктуры с открытым исходным кодом, который поможет вам создать сервис, используя лучшие практики, используемые на сегодняшний день. Итак, в этом руководстве мы покажем, как создать простой сервис с помощью Mify на классическом примере — приложении для работы со списком дел.
Предпосылки
- Установите Go 1.18+, Докер
- Загрузите Mify с нашего GitHub: https://github.com/mify-io/mify
- Установите Postman или закрутите для проверки конечных точек
Прежде чем приступить к этому руководству, вот ссылка на полный пример: https://github.com/mify- io/todo-приложение-пример
Создание проекта
После установки Mify для запуска проекта необходимо создать рабочее пространство:
$ mify init todo-app
$ cd todo-app
Перейдя в новое рабочее пространство, запустите:
$ mify add service todo-backend
Теперь это создаст шаблон Go для вашего бэкэнда. Вот упрощенное дерево рабочей области со всеми сгенерированными файлами:
.
├── go-services
│ ├── cmd
│ │ ├── dev-runner
│ │ │ └── main.go
│ │ └── todo-backend
│ │ ├── Dockerfile
│ │ └── main.go
│ ├── go.mod
│ ├── go.sum
│ └── internal
│ ├── pkg
│ │ └── generated
│ │ ├── configs
│ │ │ └── ...
│ │ ├── consul
│ │ │ └── ...
│ │ ├── logs
│ │ │ └── ...
│ │ └── metrics
│ │ └── ...
│ └── todo-backend
│ ├── app
│ │ ├── request_extra.go
│ │ ├── router
│ │ │ └── router.go
│ │ └── service_extra.go
│ └── generated
│ ├── api
| | └── ...
│ ├── app
│ │ └── ...
│ ├── apputil
│ │ └── ...
│ └── core
│ └── ...
├── schemas
│ └── todo-backend
│ ├── api
│ │ └── api.yaml
│ └── service.mify.yaml
└── workspace.mify.yaml
Mify примерно соответствует одному из распространенных макетов Go, который подходит для нескольких сервисов в одном репозитории. В internal/pkg/generated
есть общие библиотеки для конфигураций, журналов и метрик, которые можно повторно использовать для нескольких служб. Каталог вашего сервиса находится в internal/todo-backend
.
На данный момент этот сервис почти пуст, поэтому нам нужно добавить к нему API.
Определение API
Вы можете найти схему OpenAPI для todo-backend в файле schemas/todo-backend/api/api.yaml
. Каталог Schemas в корне рабочей области — это место, где хранятся все конфигурации служб, связанные с Mify.
Давайте создадим простой CRUD API для вашего бэкенда todo:
POST /todos
для добавления новых заметок о делах.PUT,GET,DELETE /todos/{id}
для их обновления, извлечения и удаления.
Вот как будет выглядеть ваша схема OpenAPI для этого API:
https://gist.github.com/chebykinn/5dc7b30a2a57a1ab4584895131295e1f
Замените предыдущую схему этой и запустите mify generate
. Вы можете запускать его каждый раз при обновлении схемы, и он будет заново генерировать все измененные данные.
Создание и тестирование
$ cd go-services
$ go mod tidy
$ go run ./cmd/todo-backend
Вы должны увидеть такие журналы запуска:
Вы можете увидеть порт службы в сообщении журнала starting api server
, скопировать его в Postman и попробовать вызвать какой-нибудь обработчик API:
Вы можете видеть, что обработчик ничего не вернул, чего и следовало ожидать, поскольку, судя по ошибке, он еще не реализован.
Добавление моделей и фиктивных хранилищ
Во-первых, нам нужно создать модель для заметки todo, мы поместим ее в пакет domain
в go-services/internal/todo-backend/domain/todo.go
:
https://gist.github.com/chebykinn/0c2905f07d76082bd9d63a56a720371c?embedable=true р>
Это также хорошее место для определения интерфейса хранилища, что полезно для отделения логики сохраняемости от приложения. В этом руководстве мы будем использовать фиктивное хранилище в памяти, но Mify также поддерживает Postgres, который мы можем добавить позже в следующей статье. Давайте поместим хранилище в go-services/internal/todo-backend/storage/todo_mem.go:
https://gist.github.com/chebykinn/1769d6881e929bfb225fc203c48e1496?embedable=true р>
Это все, что касается логики, нам просто нужно добавить ее в обработчики.
Реализация обработчиков
go-services/internal/todo-backend/handlers/todos/service.go
для метода POST и
go-services/internal/todo-backend/handlers/todos/id/service.go
для остальных.
Вот пример заглушки метода POST:
https://gist.github.com/chebykinn/e49b483330ea7c84a1b8082b0a86fc01?embedable=true р>
Теперь давайте реализуем все обработчики.
go-services/internal/todo-backend/handlers/todos/service.go
:
https://gist.github.com/chebykinn/6f88c03680167c4dc286f1b6226341f9?embedable=true р>
Не забудьте обновить импорт:
import (
"net/http"
"strconv"
"example.com/namespace/todo-app/go-services/internal/todo-backend/domain"
"example.com/namespace/todo-app/go-services/internal/todo-backend/generated/api"
"example.com/namespace/todo-app/go-services/internal/todo-backend/generated/apputil"
"example.com/namespace/todo-app/go-services/internal/todo-backend/generated/core"
"example.com/namespace/todo-app/go-services/internal/todo-backend/handlers"
)
go-services/internal/todo-backend/handlers/todos/id/service.go
:
https://gist.github.com/chebykinn/98d2d051671dfbefb464b1f59b159d15?embedable=true р>
А вот и импорт для них:
import (
"errors"
"fmt"
"net/http"
"strconv"
"example.com/namespace/todo-app/go-services/internal/todo-backend/domain"
"example.com/namespace/todo-app/go-services/internal/todo-backend/generated/api"
"example.com/namespace/todo-app/go-services/internal/todo-backend/generated/apputil"
"example.com/namespace/todo-app/go-services/internal/todo-backend/generated/core"
"example.com/namespace/todo-app/go-services/internal/todo-backend/handlers"
"example.com/namespace/todo-app/go-services/internal/todo-backend/storage"
)
Логика обработчика довольно проста, мы просто конвертируем сгенерированные модели OpenAPI в наше приложение и обратно, и чтобы избежать дублирования в коде, вот хелпер для создания ответа TodoNode, который используется в этих реализациях:
go-services/internal/todo-backend/handlers/common.go
:
https://gist.github.com/chebykinn/702f24abe035cd99dbc06c4447ecc755?embedable=true р>
Повторное тестирование
Во-первых, мы можем добавить новую заметку о задаче с помощью POST-запроса:
Проверьте, добавлен ли он с помощью запроса GET:
Обновите его с помощью запроса PUT:
Удалить:
И еще раз запустите GET, чтобы проверить, был ли он удален:
Что дальше
- Постоянное хранилище, например Postgres,
- Конфигурация,
- Промежуточное ПО для аутентификации
- Развертывание в облаке.
Большая часть этого материала описана в наших документах, так что ознакомьтесь с ними: https://mify.io/docs, но оставайтесь настроены для следующих статей.
Также опубликовано здесь
Оригинал