In Go HTTP handlers, why is the ResponseWriter a v

2019-01-11 05:32发布

问题:

I'm learning Go by writing an app for GAE, and this is signature of a handler function:

func handle(w http.ResponseWriter, r *http.Request) {}

I'm pointer newbie here, so why is the Request object a pointer, but the ResponseWriter not? Is there any need to have it this way or is this just to make some kind of advanced pointer based code possible?

回答1:

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 precise it explicitely :

From request.go :

type Request struct {
    ...
}


回答2:

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.



回答3:

The reason why it’s a pointer to Request is simple: changes to Request by the handler need to be visible to the server, so we’re only passing it by reference instead of by value.

If you dig into the net/http library code, you’ll find that ResponseWriter is an interface to a nonexported struct response, and we’re passing the struct by reference (we’re passing in a pointer to response) and not by value. ResponseWriter is an interface that a handler uses to create an HTTP response. The actual struct backing up ResponseWriter is the nonexported struct http.response. Because it’s nonexported, you can’t use it directly; you can only use it through the ResponseWriter interface.

In other words, both the parameters are passed in by reference; it’s just that the method signature takes a ResponseWriter that’s an interface to a pointer to a struct, so it looks as if it’s passed in by value.



回答4:

I think that the main reason for the Request object to be passed as a pointer is the Body field. For a given HTTP request, the body can only we read once. If the Request object was cloned, as it would be if it wasn't passed as a pointer, we would have two objects with different information about how much has been read from the body.



标签: pointers go