Напиши функцию, которая делает GET-запрос по адресу и возвращает тело ответа
или ошибку.
// StatusError — сервер ответил не 2xx.
type StatusError struct {
Code int
}
func (e *StatusError) Error() string
// Get выполняет GET-запрос через клиента c (nil — клиент по умолчанию с таймаутом).
func Get(ctx context.Context, c *http.Client, url string) ([]byte, error)
Требования
- Ответ 2xx → тело целиком и
nil.
- Любой другой статус →
nil и *StatusError с кодом ответа (достаётся через
errors.As).
- Тело ответа закрывается всегда, в том числе при плохом статусе.
- Запрос уважает
ctx: при отмене или дедлайне функция возвращает ошибку, для
которой errors.Is(err, context.DeadlineExceeded) (или Canceled).
- Невалидный URL или сетевая ошибка → ошибка, без паники.
c == nil → используется клиент с таймаутом, а не http.DefaultClient.
Пример
body, err := Get(ctx, nil, "https://example.com/health")
var se *StatusError
if errors.As(err, &se) && se.Code == http.StatusNotFound { ... }
var ErrTooLarge = errors.New("response body too large")
// GetLimited — как Get, но тело больше max байт → ErrTooLarge.
func GetLimited(ctx context.Context, c *http.Client, url string, max int64) ([]byte, error)
- Тело ровно
max байт — нормально. На max+1 — ErrTooLarge, и в память не
читается больше max+1 байт.
Устно: что будет, если не закрыть resp.Body? Зачем дочитывать тело
перед закрытием? Почему http.Get без таймаута опасен в проде?
Разбор и эталонное решение — после своей попытки: на собеседовании подсказок не будет.
Сначала попробуй сам — подсказки не дают готовый ответ.