> Какова структура HTTP-ответа (Go)
Уровень: middle · Роль: backend · Категория: Технические вопросы
Компании: Ozon
Стек: Go
> Пример ответа
Короткий ответ
HTTP-ответ - это структурированное сообщение от сервера клиенту, состоящее из трёх частей: статусной строки (status line), заголовков (headers) и тела (body). Статусная строка содержит версию протокола, код статуса (например, 200 OK) и текстовое описание. Заголовки передают метаданные: Content-Type, Content-Length, Cache-Control и другие. Тело содержит полезную нагрузку - JSON, HTML, файл или пустоту. В Go структура ответа формируется через net/http, где статус и заголовки задаются до вызова Write.
Подробное объяснение
HTTP-ответ (response) - это сообщение, которое сервер отправляет клиенту после обработки запроса. Формат определён в RFC 7230 и выглядит так:
HTTP/1.1 200 OK Content-Type: application/json Content-Length: 27 {"message":"hello"}
Разбор по частям:
-
Status line - первая строка:
HTTP/1.1 200 OK. Содержит:- версию протокола (HTTP/1.1, HTTP/2);
- трёхзначный код статуса (status code) - 1xx информационные, 2xx успех, 3xx редирект, 4xx ошибка клиента, 5xx ошибка сервера;
- reason phrase - человекочитаемое описание (может быть пустым).
-
Headers - блок строк вида
Name: value, заканчивается пустой строкой. Ключевые заголовки:Content-Type- формат тела (application/json, text/html);Content-Length- размер тела в байтах;Transfer-Encoding: chunked- если длина неизвестна заранее;Set-Cookie,Cache-Control,Location(для 3xx) и другие.
-
Body - опциональная часть, отделённая от заголовков пустой строкой. Может быть пустым (например, в 204 No Content или 304 Not Modified). В HTTP/2 тело передаётся в DATA frames, но логическая структура сохраняется.
В Go структура ответа управляется через http.ResponseWriter:
WriteHeader(code)- устанавливает статус (по умолчанию 200);Header().Set(key, value)- задаёт заголовки до вызова Write;Write(body)- записывает тело, автоматически устанавливая Content-Length, если тело записано одним вызовом.
На практике
Для backend-разработчика важно понимать, как правильно формировать ответы в Go:
- Всегда устанавливайте
Content-Typeявно, иначе Go определит его черезhttp.DetectContentTypeпо первым 512 байтам тела - это может дать неожиданный результат. - Вызывайте
WriteHeaderтолько один раз - повторный вызов игнорируется и логируется. - Если вы пишете в
ResponseWriterпослеWriteHeader, заголовки уже не изменятся. - Для JSON-ответов используйте
json.NewEncoder(w).Encode(v)- это автоматически добавитContent-Type: application/json(если не задан) и корректно экранирует HTML. - Для потоковой передачи (streaming) используйте
http.Flusher- при этомContent-Lengthне устанавливается, а используется chunked encoding. - Статус 204 No Content не должен иметь тела - Go сам уберёт Content-Length при пустом теле.
Пример кода
GOpackage mainimport ("encoding/json""net/http")type User struct {ID int `json:"id"`Name string `json:"name"`}func handler(w http.ResponseWriter, r *http.Request) {// Явно задаём заголовки до WriteHeaderw.Header().Set("Content-Type", "application/json")w.Header().Set("X-Request-ID", r.Header.Get("X-Request-ID"))user := User{ID: 1, Name: "Alice"}// Статус по умолчанию 200, но можно задать явноw.WriteHeader(http.StatusOK)// Кодируем JSON прямо в ResponseWriterif err := json.NewEncoder(w).Encode(user); err != nil {// Если ошибка после WriteHeader - статус уже отправленhttp.Error(w, "internal error", http.StatusInternalServerError)}}func main() {http.HandleFunc("/user", handler)http.ListenAndServe(":8080", nil)}
Как отвечать на собеседовании
Начните с краткого перечисления трёх частей ответа, затем раскройте каждую. Обязательно упомяните:
- разницу между status code и reason phrase;
- роль заголовков Content-Type и Content-Length;
- как Go обрабатывает порядок: заголовки → WriteHeader → Write;
- поведение при повторном WriteHeader (игнорируется);
- что происходит при записи тела без явного Content-Length (chunked или автоопределение).
Если спросят про HTTP/2 - отметьте, что структура логически та же, но передача идёт бинарными фреймами, а заголовки сжимаются HPACK.
Что проверяет интервьюер
Интервьюер оценивает:
- базовое понимание протокола HTTP, а не только фреймворков;
- знание порядка операций в Go при формировании ответа;
- понимание edge cases: пустое тело, статусы без тела, потоковая передача;
- умение объяснить, почему нельзя менять заголовки после WriteHeader;
- знание типичных кодов статусов и их семантики.
Типичные ошибки
- Запись заголовков после вызова
WriteилиWriteHeader- они не применятся. - Установка
Content-Lengthвручную при использованииjson.Encoder- может привести к рассинхронизации. - Игнорирование ошибки от
Encode- если соединение оборвалось, клиент получит обрезанный ответ. - Возврат 200 при ошибке бизнес-логики - нужно использовать 4xx/5xx.
- Забывают про
http.Errorдля простых текстовых ошибок - он сам устанавливает Content-Type и статус. - Путают
WriteHeader(200)сWrite- если вызватьWriteбезWriteHeader, статус будет 200, но это неявное поведение, лучше задавать явно.
> Похожие задачи по backend
В чем различия между стеком и хипом в Go
Какова асимптотическая сложность доступа по ключу в хэш-таблице
Можно ли передать функцию как аргумент в другую функцию в Go
Как использовать EXPLAIN и ANALYZE для оптимизации SQL запросов
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью