Better HTTP/1 connection reuse in Go 1.27
В пакете net/http языка Go появилось важное улучшение: начиная с версии 1.27 транспорт автоматически асинхронно вычитывает неиспользованное тело HTTP/1-ответа — до 50 миллисекунд или 256 КБ. Это позволяет переиспользовать соединение вместо создания нового. На практике функция, которая просто вызывает http.Get и закрывает тело, стала почти в пять раз быстрее: 100 запросов к index.golang.org заняли около 150 мс против 710 мс в Go 1.26.
Причина в стоимости установки соединения. Каждый новый запрос по HTTP/1 требует TCP-рукопожатия (1 RTT), затем TLS-рукопожатия (2 RTT по TLS 1.2 или 1 RTT по TLS 1.3) — итого до 3 RTT только на подготовку. При межрегиональной задержке в 100 мс RTT это сотни миллисекунд накладных расходов. Переиспользование соединений решает проблему: в HTTP/1.1 они постоянны по умолчанию, а в HTTP/2 запросы мультиплексируются в одном TCP-соединении.
Однако переиспользование ломается, если тело ответа не вычитано до конца: данные остаются в потоке байтов и мешают следующему запросу. Раньше разработчикам приходилось вручную вычитывать тело с таймаутом, что было громоздко и порождало ошибки — например, бессмысленное вычитывание для HTTP/2. Теперь Transport делает это сам, пропуская операцию при заголовке Connection: close. Рекомендация прежняя: просто закрывайте тело через defer resp.Body.Close() и не усложняйте код.