slices pointer make golang for array pointers go

pointers - make - En los controladores Go HTTP, ¿por qué el ResponseWriter es un valor pero el Request a pointer?



slice en go (4)

Creo que la razón principal para que el objeto Request se pase como un puntero es el campo Body . Para una solicitud HTTP dada, el cuerpo solo puede leer una vez. Si el objeto Request se clonó, como sería si no se pasara como un puntero, tendríamos dos objetos con información diferente sobre cuánto se ha leído del cuerpo.

Estoy aprendiendo Go escribiendo una aplicación para GAE, y esta es la firma de una función de controlador:

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

Soy un novato de puntero aquí, entonces ¿por qué el objeto Request un puntero, pero el ResponseWriter no? ¿Hay alguna necesidad de tenerlo de esta manera o solo para hacer posible algún tipo de código basado en un puntero avanzado?


La razón por la que es un puntero a Solicitar es simple: los cambios en la Solicitud por parte del controlador deben ser visibles para el servidor, por lo que solo lo pasamos por referencia en lugar de por valor.

Si profundiza en el código de la biblioteca net / http, encontrará que ResponseWriter es una interfaz para una respuesta de estructura no exportada, y estamos pasando la estructura por referencia (estamos pasando un puntero a la respuesta) y no por valor . ResponseWriter es una interfaz que un controlador utiliza para crear una respuesta HTTP. La estructura de respaldo real ResponseWriter es la estructura no exportada http.response. Como no está exportado, no puede usarlo directamente; solo puede usarlo a través de la interfaz ResponseWriter.

En otras palabras, ambos parámetros se pasan por referencia; es solo que la firma del método lleva un ResponseWriter que es una interfaz a un puntero a una estructura, por lo que parece que se transfiere por valor.


Lo que obtienes para w es un puntero al tipo de ResponseWriter http.response no exportado pero como ResponseWriter es una interfaz, eso no está visible.

Desde server.go :

type ResponseWriter interface { ... }

Por otro lado, r es un puntero a una estructura concreta, de ahí la necesidad de precisarlo explícitamente:

De request.go :

type Request struct { ... }


http.ResponseWriter es una interfaz y los tipos existentes que implementan esta interfaz son punteros. Eso significa que no es necesario utilizar un puntero a esta interfaz, ya que ya está "respaldado" por un puntero. Este concepto se describe un poco por uno de los desarrolladores de Go here Aunque un tipo que implementa http.ResponseWriter no necesita ser un puntero, no sería práctico, al menos no dentro del servidor de http de go.

http.Request no es una interfaz, es solo una estructura, y como queremos cambiar esta estructura y hacer que el servidor web vea esos cambios, tiene que ser un puntero. Si solo fuera un valor de estructura, simplemente modificaríamos una copia de la que el servidor web que llama a nuestro código no podría ver.