Создание службы RESTful API в Go без повторяющихся шаблонов

Создание службы RESTful API в Go без повторяющихся шаблонов

6 марта 2023 г.

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

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

Предпосылки

Прежде чем приступить к этому руководству, вот ссылка на полный пример: 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, но оставайтесь настроены для следующих статей.


Также опубликовано здесь


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE