> Как организовать обработку успешных и неуспешных сетевых запросов (Go)

Уровень: senior · Роль: backend · Категория: Технические вопросы

Компании: Домопульт

Стек: Go

> Пример ответа

В Go обработка успешных и неуспешных сетевых запросов строится на паттерне явной проверки ошибок и использовании каналов/контекстов для управления временем жизни запроса. Основной подход:

  1. Явная обработка ошибок - каждый вызов, возвращающий ошибку, должен быть проверен:
GO
resp, err := http.Get("https://api.example.com/data")
if err != nil {
// Логируем, возвращаем fallback или ошибку
log.Printf("request failed: %v", err)
return nil, fmt.Errorf("get data: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
// Обработка HTTP-ошибок (4xx, 5xx)
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("unexpected status %d: %s", resp.StatusCode, body)
}
  1. Таймауты и контексты - для предотвращения зависаний:
GO
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
resp, err := http.DefaultClient.Do(req)
  1. Retry-логика - для временных сбоев (с exponential backoff):
GO
func doWithRetry(url string) (*http.Response, error) {
for i := 0; i < 3; i++ {
resp, err := http.Get(url)
if err == nil && resp.StatusCode < 500 {
return resp, nil
}
if resp != nil {
resp.Body.Close()
}
time.Sleep(time.Duration(math.Pow(2, float64(i))) * time.Second)
}
return nil, fmt.Errorf("all retries failed")
}
  1. Каналы для асинхронных запросов - группировка результатов:
GO
type Result struct {
Data []byte
Err error
}
func fetchAsync(url string) <-chan Result {
ch := make(chan Result, 1)
go func() {
resp, err := http.Get(url)
if err != nil {
ch <- Result{Err: err}
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
ch <- Result{Data: body}
}()
return ch
}
  1. Логирование и мониторинг - структурированные логи для успехов и ошибок:
GO
log.WithFields(log.Fields{
"url": url,
"status": resp.StatusCode,
"duration": time.Since(start),
}).Info("request completed")

Ключевые принципы: не игнорировать ошибки, всегда закрывать тела ответов, использовать контексты для контроля времени жизни, применять retry только для идемпотентных запросов.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью