In Go HTTP handlers, why is the ResponseWriter a value but the Request a pointer?

What you get for w is a pointer to the non exported type http.response but as ResponseWriter is an interface, that's not visible.

From server.go:

type ResponseWriter interface {
    ...
}

On the other hand, r is a pointer to a concrete struct, hence the need to pass a reference explicitly.

From request.go:

type Request struct {
    ...
}

The http.ResponseWriter is an interface, and the existing types implementing this interface are pointers. That means there's no need to use a pointer to this interface, as it's already "backed" by a pointer. This concept is describe a bit by one of the go develpers here Although a type implementing http.ResponseWriter didn't need to be a pointer, it would not be practical, at least not within the go http server.

http.Request is not an interface, it's just a struct, and since we want to change this struct and have the web server see those changes, it has to be a pointer. If it was just a struct value, we would just modify a copy of it that the web server calling our code could not see.