Go: Обязательная и необязательная зависимость при отказе — задача с проверкой

Практическая задача на Go по теме «Обязательная и необязательная зависимость при отказе». Условие содержит контракт функций, предоставленные типы и требования к результату. Используйте выданный шаблон и сохраняйте его публичные объявления. Перед проверкой разберите успешный путь, обработку ошибок и отмену операции, когда она предусмотрена контрактом. Здесь оценивается конкретный компонент сервиса; в полном курсе микросервисов на Go эти компоненты связываются с HTTP, PostgreSQL, gRPC и Kafka.

Обязательная и необязательная зависимость при отказе

Контекст

В пакете уже объявлены следующие типы и вспомогательная функция — повторно объявлять их не нужно:


type Core interface {
    Remaining(context.Context) (int, error)
}

type OptionalSuggestions interface {
    List(context.Context) ([]string, error)
}

type PermissionResponse struct {
    Allowed   bool `json:"allowed"`
    Remaining int  `json:"remaining"`
}

type PageResponse struct {
    Title             string   `json:"title"`
    Suggestions       []string `json:"suggestions"`
    SuggestionsStatus string   `json:"suggestions_status"`
}

type ErrorResponse struct {
    Error string `json:"error"`
}

// writeJSON устанавливает Content-Type: application/json,
// записывает status и JSON-кодированный value с завершающим переводом строки.
func writeJSON(w http.ResponseWriter, status int, value any)

Импорты context, encoding/json, net/http уже присутствуют.

Отправь только две требуемые функции. Объявление пакета, импорты и main уже предоставлены; добавлять их не нужно. Внешний код направляет в обработчики запросы с указанными методами GET и путями, поэтому дополнительная маршрутизация не требуется.

Реализации обеих зависимостей гарантированно ненулевые. При успешном вызове Core.Remaining возвращаемый remaining неотрицателен; ноль допустим.

Что требуется реализовать

Две функции с точными сигнатурами:


func PermissionHandler(core Core) http.HandlerFunc
func PageHandler(optional OptionalSuggestions) http.HandlerFunc

PermissionHandler

Обрабатывает GET /upload-permission. Вызывает core.Remaining(r.Context()) ровно один раз.

При error == nil — HTTP 200, тело типа PermissionResponse:

  • remaining — значение, возвращённое Remaining;
  • allowed — remaining > 0 (ноль означает отказ, но всё равно HTTP 200).

При ненулевом error — HTTP 503, тело типа ErrorResponse:


{"error": "core_unavailable"}

Значение remaining и текст ошибки не раскрываются; поля allowed/remaining в ответе отсутствуют.

Примеры:

Результат Remaining HTTP Тело
2, nil 200 {"allowed":true,"remaining":2}
0, nil 200 {"allowed":false,"remaining":0}
_, <error> 503 {"error":"core_unavailable"}

PageHandler

Обрабатывает GET /page. Вызывает optional.List(r.Context()) ровно один раз. Всегда возвращает HTTP 200, тело типа PageResponse.

  • title — всегда строка "Uploads".
  • При error == nil: suggestions — возвращённый список (пустой или nil сериализуется как [], не null), suggestions_status — "available".
  • При ненулевом error: suggestions — пустой массив [], suggestions_status — "unavailable"; частичные данные, сопровождающие ошибку, игнорируются.

Примеры:

Результат List HTTP Тело
nil, nil 200 {"title":"Uploads","suggestions":[],"suggestions_status":"available"}
["stale"], <error> 200 {"title":"Uploads","suggestions":[],"suggestions_status":"unavailable"}
["cats","dogs"], nil 200 {"title":"Uploads","suggestions":["cats","dogs"],"suggestions_status":"available"}

Общие ограничения

  • Каждый обработчик вызывает только свою зависимость, ровно один раз, передавая r.Context().
  • Не кешировать результаты между запросами и между экземплярами обработчика.
  • Не запускать горутины, не делать повторных вызовов, не выполнять HTTP-запросы вручную.
  • Ошибку не классифицировать по строке: любой ненулевой error обрабатывается одинаково согласно политике своей зависимости.
  • Дополнительные JSON-поля в ответе не добавлять.

Подсказки

  • При успехе List замени только nil-слайс на []string{}, чтобы получить JSON-массив []; ненулевой успешный список сохрани без изменения. При ошибке используй пустой слайс, отбрасывая сопровождающие данные.
  • В PermissionHandler сначала проверьте error и выберите статус, затем вызовите writeJSON один раз — так статус гарантированно будет выставлен до записи тела.

Запуск на Latorn: редактируйте реализацию в полном шаблоне, сохраняя предоставленные объявления и публичный адаптер RunScenarios. main не требуется. Адаптер принимает массив сценариев и возвращает наблюдения; ожидаемые результаты сравниваются отдельно на сервере. Для собственного запуска аргументы — JSON-массив с одним массивом сценариев: [[...]].

РешениеGo

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

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

Связанные задачи