Модель данных и назначение
Реализуйте REST API событий на Go. Сервис хранит записи только в памяти процесса и не подключается к базе данных. Событие содержит id, title, startsAt и capacity; startsAt принимает момент времени в UTC в формате RFC 3339, capacity является целым числом больше нуля. Идентификаторы генерируются сервером, клиент не может назначить или изменить id. При запуске хранилище пустое; перезапуск процесса очищает его.
API, проверки и эксплуатация
POST /api/events создаёт событие и возвращает 201 с созданной записью. Обязательны непустой title после удаления крайних пробелов, длина title от 1 до 160 символов, корректный startsAt в UTC и capacity от 1 до 100000. Некорректный JSON или поля дают 400 с устойчивым кодом ошибки и полем, которое не прошло проверку. GET /api/events принимает limit и offset: limit по умолчанию 20, допустим от 1 до 100; offset по умолчанию 0 и не может быть отрицательным. Ответ содержит items, limit, offset и total. Список сортируется по startsAt по возрастанию, затем по id, чтобы порядок оставался детерминированным при одинаковом времени.
GET /api/events/{id} возвращает событие или 404. PUT /api/events/{id} полностью заменяет title, startsAt и capacity после тех же проверок, сохраняет id и отвечает 200; отсутствующая запись даёт 404. DELETE /api/events/{id} удаляет запись и отвечает 204, повторное удаление возвращает 404. Все маршруты имеют префикс /api, неподдерживаемый метод возвращает 405, неизвестный маршрут — 404. Для ошибок используется единый JSON-формат без внутренних подробностей. Ограничьте размер тела запроса, отклоняйте неизвестные JSON-поля и второй JSON-объект в одном теле. Сервер корректно завершает HTTP-обработку при отмене контекста и имеет конечные таймауты чтения, записи и заголовков. Параллельные запросы не должны повреждать записи или выдавать частично обновлённое состояние; конкурентный доступ к хранилищу защищается синхронизацией. Пустая страница при offset больше total возвращает пустой items и исходный total, а параметры limit и offset с неверным числовым форматом дают 400. Секретов и внешних провайдеров у сервиса нет; журнал содержит только полезные операционные события и не копирует пользовательские значения без необходимости.
Структура программы
Небольшой internal/httpapi содержит обработчики и DTO, internal/events — проверки и CRUD-правила, internal/eventmemory — потокобезопасное хранилище в памяти. main.go читает конфигурацию, связывает пакеты, запускает сервер и завершает его по сигналу; правила тестируются без HTTP.