Go 1.27 leert ungelesene HTTP/1-Bodys selbst – das alte Leeren vor dem Schließen kann weg
Ein Beitrag im Go-Blog vom 14. Oktober 2026 erklärt eine alte Stolperfalle in net/http und die Änderung in Go 1.27, die sie beseitigt. Der Einstiegs-Benchmark ist eine Funktion, die eine GET-Anfrage sendet und nur den Statuscode zurückgibt: 100 Aufrufe gegen index.golang.org über HTTP/1 dauern auf dem Rechner des Autors etwa 710 ms mit Go 1.26 und etwa 150 ms mit Go 1.27.
Warum der alte Code langsam war. Eine neue Verbindung kostet vor der ersten Anfrage einen TCP- und einen TLS-Handshake – der Beitrag rechnet mit TLS 1.2 etwa drei Round-Trips. HTTP/1-Clients vermeiden das durch Wiederverwendung von Verbindungen, aber bei HTTP/1 kommen die Antworten hintereinander im selben Bytestrom an. net/http findet den Beginn der nächsten Antwort erst, wenn der aktuelle Body bis zum Ende gelesen ist. Bis Go 1.26 verwarf der Transport die Verbindung, wenn eine Antwort mit ungelesenem Body geschlossen wurde, und baute für die nächste Anfrage eine neue auf.
Wo es zuschlug. Der Beitrag nennt zwei Fälle: einen Client, der nur den Statuscode braucht, während der Server einen kleinen Body schickt, den niemand liest; und Code, der den Body zwar liest, aber kurz vor dem Ende aufhört – encoding/json.Decoder stoppt an der schließenden }, sodass ein abschließender Zeilenumbruch die Verbindung ein Byte vor der Wiederverwendbarkeit stehen ließ. HTTP/2 kennt das Problem nicht, weil es Streams über eine Verbindung multiplext.

Der Workaround, den alle schrieben. Entwickler leerten Bodys vor dem Schließen – io.Copy(io.Discard, body). Der Beitrag zeigt, warum das schwieriger ist, als es aussieht: Ein unbegrenztes Leeren kann bei großen Bodys langsamer sein als eine neue Verbindung, braucht also eine Byte-Grenze; ein langsamer Body braucht eine Zeitgrenze; und damit das Schließen nicht blockiert, muss das Leeren in den Hintergrund. Außerdem habe sich die Praxis auf HTTP/2 übertragen, wo das Leeren unnötig ist.
Was Go 1.27 macht. net/http.Transport leert einen ungelesenen HTTP/1-Body jetzt asynchron, für höchstens 50 ms oder 256 KB, und verzichtet darauf, wenn die Antwort Connection: close trägt, weil die Arbeit dann vergeblich wäre. Laut Go-Team kann sich das Verhalten noch ändern.
Die Empfehlung daraus. Der Beitrag rät, Response-Bodys einfach zu schließen, sobald sie nicht mehr gebraucht werden, und die Wiederverwendung net/http zu überlassen – handgeschriebene Leer-Helfer in HTTP/1-Clients werden damit nach dem Umstieg auf Go 1.27 zu Kandidaten zum Löschen.
Quelle: The Go Blog, „Better HTTP/1 connection reuse“ — https://go.dev/blog/http-connection-reuse