> Как организовать обработку успешных и неуспешных сетевых запросов (Go)
Уровень: senior · Роль: backend · Категория: Технические вопросы
Компании: Домопульт
Стек: Go
> Пример ответа
В Go обработка успешных и неуспешных сетевых запросов строится на паттерне явной проверки ошибок и использовании каналов/контекстов для управления временем жизни запроса. Основной подход:
- Явная обработка ошибок - каждый вызов, возвращающий ошибку, должен быть проверен:
GOresp, 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)}
- Таймауты и контексты - для предотвращения зависаний:
GOctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)defer cancel()req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)resp, err := http.DefaultClient.Do(req)
- Retry-логика - для временных сбоев (с exponential backoff):
GOfunc 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")}
- Каналы для асинхронных запросов - группировка результатов:
GOtype Result struct {Data []byteErr 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}
- Логирование и мониторинг - структурированные логи для успехов и ошибок:
GOlog.WithFields(log.Fields{"url": url,"status": resp.StatusCode,"duration": time.Since(start),}).Info("request completed")
Ключевые принципы: не игнорировать ошибки, всегда закрывать тела ответов, использовать контексты для контроля времени жизни, применять retry только для идемпотентных запросов.
> Похожие задачи по backend
Может ли приложение работать в нескольких процессах?
Как реализована аутентификация с поддержкой OpenID и OAuth 2.0
Что такое garbage collector и как он работает
Что такое достижимая и недостижимая ссылка в сборщике мусора
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью