Какую архитектуру и технологии использовать для реализации клиента чата с REST API?
Что проверяют
Умеете ли вы спроектировать клиент, который живёт в ненадёжной сети: таймауты, повторы, лимиты, порядок сообщений. Следом почти всегда спрашивают, как получать новые сообщения, если у API нет WebSocket.
Как отвечать
Уточните роль клиента: консольное приложение, бот или сервис-интеграция. Каркас на Go от этого почти не меняется:
- транспорт: свой
http.ClientсTimeoutи настроеннымTransport(пул соединений,IdleConnTimeout), каждый запрос сcontext.Context, чтобы его можно было отменить; - API-клиент: типизированные методы
SendMessage,ListMessagesповерх транспорта. Если у сервера есть OpenAPI, клиент можно сгенерировать черезoapi-codegen; - устойчивость: повторы только на сетевые ошибки, 5xx и 429, с экспоненциальной задержкой и джиттером, с учётом заголовка
Retry-After. Частоту ограничиваетgolang.org/x/time/rate; - новые сообщения: long polling или опрос с курсором (
after_idили токен страницы), а не выкачивание истории. Если сервер умеет SSE или WebSocket, для реального времени лучше они, REST остаётся для истории и отправки; - конкурентность: горутина опроса отдаёт сообщения в канал, остановка через отмену контекста, группа горутин через
errgroup; - локальное состояние: последний курсор и кэш сообщений, дедупликация по ID.
Отдельно скажите про отправку: при повторе POST сообщение может задвоиться, поэтому клиент генерирует ключ идемпотентности и шлёт его в заголовке, если API это поддерживает. Тестируется всё через httptest.Server и интерфейс клиента, который легко подменить.
Где спотыкаются
Используют http.Get или http.DefaultClient. У клиента по умолчанию нет таймаута, и зависшее соединение навсегда блокирует горутину.
Не закрывают resp.Body или не дочитывают его. Соединение не возвращается в пул, и под нагрузкой клиент упирается в лимит файловых дескрипторов.
Опрашивают сервер в цикле без задержки и без курсора. Получают 429, дубли и пропуски сообщений, пришедших между двумя запросами с одинаковой меткой времени.