Go 1.27 now drains unread HTTP/1 bodies for you — and the old drain-before-close habit can go
A post on the Go blog published on 14 October 2026 walks through a long-standing sharp edge in net/http and the change in Go 1.27 that removes it. Its opening benchmark is a function that sends a GET request and returns only the status code: called 100 times against index.golang.org over HTTP/1, it takes about 710 ms on Go 1.26 and about 150 ms on Go 1.27 on the author's machine.
Why the old code was slow. A new connection costs a TCP handshake and a TLS handshake before the first request — the post counts about three round trips with TLS 1.2. HTTP/1 clients avoid that by reusing connections, but on HTTP/1 responses arrive back to back on the same byte stream. net/http can only find the start of the next response after the current body has been read to its end. Through Go 1.26, closing a response whose body was still unread made the transport abandon the connection and open a new one for the next request.
Where it bit. The post lists two cases. A client that only wants the status code, while the server sends a small body nobody reads. And code that does read the body but stops just short of the end: encoding/json.Decoder stops at the closing }, so a trailing newline left a connection one byte away from reusable. HTTP/2 does not have the problem, because it multiplexes streams over one connection.

The workaround everyone wrote. Developers drained bodies before closing them — io.Copy(io.Discard, body). The post shows why that is harder than it looks: an unbounded drain can be slower than a new connection for a large body, so it needs a byte cap; a slow body needs a time cap; and blocking on close needs moving the drain into the background. It also notes the practice spread to HTTP/2, where draining is unnecessary.
What Go 1.27 does. net/http.Transport now drains an unread HTTP/1 response body asynchronously, for up to 50 ms or 256 KB, and skips draining when the response carries Connection: close, since that work would be wasted. The Go team says the behaviour may evolve.
The recommendation that follows. The post's advice is to simply close response bodies once they are no longer needed and let net/http handle reuse — which means hand-written drain helpers in HTTP/1 clients become candidates for deletion after moving to Go 1.27.
Source: The Go Blog, "Better HTTP/1 connection reuse" — https://go.dev/blog/http-connection-reuse