Ответ
В Go есть несколько способов установить таймаут для HTTP-запроса, каждый из которых подходит для разных сценариев.
Способ 1: http.Client.Timeout
(Простой и общий)
Это самый простой способ. Timeout
устанавливает общий лимит времени на весь запрос, включая установку соединения, отправку запроса и чтение всего тела ответа.
client := &http.Client{
Timeout: 5 * time.Second, // Общий таймаут
}
resp, err := client.Get("https://example.com")
if err != nil {
// Ошибка может быть вызвана таймаутом, например: context.DeadlineExceeded
log.Fatal(err)
}
defer resp.Body.Close()
Способ 2: context.WithTimeout
(Гибкий и предпочтительный)
Использование контекста — более современный и гибкий подход. Он позволяет отменить запрос не только по таймауту, но и по другим причинам (например, если пользователь отменил операцию). Контекст передается через всю цепочку вызовов.
// Создаем контекст с таймаутом в 5 секунд
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel() // Важно вызывать cancel, чтобы освободить ресурсы
req, _ := http.NewRequestWithContext(ctx, "GET", "https://example.com", nil)
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
Способ 3: http.Transport
(Детальный контроль)
Для тонкой настройки таймаутов на разных этапах запроса можно сконфигурировать http.Transport
.
client := &http.Client{
Transport: &http.Transport{
DialContext: (&net.Dialer{
Timeout: 3 * time.Second, // Таймаут на установку TCP-соединения
}).DialContext,
TLSHandshakeTimeout: 4 * time.Second, // Таймаут на TLS-рукопожатие
ResponseHeaderTimeout: 5 * time.Second, // Таймаут на ожидание заголовков ответа
},
}
resp, err := client.Get("https://example.com")
// ...
Какой способ выбрать?
Client.Timeout
: Для простых утилит и быстрых скриптов.context.WithTimeout
: Предпочтительный способ для большинства приложений, особенно для серверных, где важна управляемая отмена операций.http.Transport
: Для случаев, когда нужен гранулярный контроль над сетевыми таймаутами (например, для обнаружения медленных серверов, которые долго устанавливают соединение, но быстро отвечают).