After the status line come the response headers, one per line, until a blank line ends them. Today you parse that block into the same case-insensitive header collection the request side uses.
Parse header lines into the header collection until the blank line, trimming whitespace after the colon.
The headers follow the status line, one field per line, and the block ends at the blank line - the same boundary you emit when building a request, now read from the other side. Each line is a name, a colon, optional whitespace, and a value; you split on the colon, trim the surrounding whitespace off the value, and store it into the case-insensitive header collection you built in chapter two. Reuse pays off: the container is identical whether the header came from your code or the server’s.
Split each line on the first colon only. Many header values carry colons of
their own - a Date holds a time like 15:04:05, a Location holds a URL - and
splitting greedily on every colon would truncate them. The name is what precedes the
first colon; the value is everything after, with just its surrounding whitespace
trimmed. The loop reads lines until it hits the empty one, which it consumes and
stops on - leaving the reader sitting exactly at the first byte of the body. That
precise positioning is what lets the next lessons read the body by length.
// read lines until an EMPTY line (the end of the block). each// line is "Name:" + optional-whitespace + "Value"; split on the// FIRST colon only (so a value like a Date keeps its own colons)// and trim leading/trailing spaces from the value.// store into the case-insensitive Header from chapter two.func (r *reader) parseHeaders() (*Header, error) {// loop readLine until ""; Set(name, trimmed value)}