En las secciones anteriores, hemos aprendido sobre el flujo de trabajo de la web, y hablamos un poco sobre el paquete http
. En esta sección, vamos a aprender dos funciones básicas que estan en el paquete http
: Conn, ServeMux.
A diferencia de los servidores HTTP normales , Go utiliza goroutine para toda conexion que creó Conn con el fin de lograr una alta concurrencia y rendimiento, por lo que cada caso es independiente.
Go usa el siguiente código para esperar a nuevas conexiones de clientes .
c, err := srv.newConn(rw)
if err != nil {
continue
}
go c.serve()
Como puede ver, se crea una goroutine para cada conexión , y se pasa el controlador que es capaz de leer los datos de solicitud a la goroutine .
Utilizamos el enrutamiento por defecto en la sección anterior, cuando se habla conn.server , el router pasa los datos de solicitud como back-end al controlador.
El struct del router por defecto:
type ServeMux struct {
mu sync.RWMutex //debido a la concurrencia, tenemos que utilizar mutex aquí
m map[string]muxEntry //routers, cada asignación de cadena a un controlador
}
El struct de muxEntry:
type muxEntry struct {
explicit bool // exact match or not
h Handler
}
La interfaz de Handler:
type Handler interface {
ServeHTTP(ResponseWriter, *Request) // routing implementer
}
Handler
es una interfaz, pero la función sayhelloName
no implementar su interfaz , por eso podríamos agregarlo como controlador ? Debido a que hay otro tipo HandlerFunc
en el paquete http
. Llamamos HandlerFunc
definir nuestra sayhelloName
, así sayhelloName
implementa el Handler
al mismo tiempo. que es como llamamos HandlerFunc(f)
, y la función f
es forzado convertido al tipo HandlerFunc
.
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
Cómo enrutador llama los controladores después de establecer reglas del router ?
El enrutador llama mux.handler.ServeHTTP(w , r)
cuando recibe solicitudes. En otras palabras, se llama la interfaz ServeHTTP
de los controladores.
Ahora, vamos a ver cómo funciona mux.handler
.
func (mux *ServeMux) handler(r *Request) Handler {
mux.mu.RLock()
defer mux.mu.RUnlock()
// Host-specific pattern takes precedence over generic ones
h := mux.match(r.Host + r.URL.Path)
if h == nil {
h = mux.match(r.URL.Path)
}
if h == nil {
h = NotFoundHandler()
}
return h
}
El router utiliza la URL como clave para encontrar correspondiente controlador que guarda en un mapa , y llama handler.ServeHTTP para ejecutar funciones para manejar los datos.
Usted debe entender el flujo de trabajo del router, y Go realmente apoya routers personalizados. El segundo argumento de ListenAndServe es para la configuración del router a medida, que es una interfaz de Handler
. Por lo tanto , se puede utilizar cualquier router que implemente la interfaz Handler
.
El siguiente ejemplo muestra cómo implementar un enrutador sencillo.
package main
import (
"fmt"
"net/http"
)
type MyMux struct {
}
func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
sayhelloName(w, r)
return
}
http.NotFound(w, r)
return
}
func sayhelloName(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello myroute!")
}
func main() {
mux := &MyMux{}
http.ListenAndServe(":9090", mux)
}
Vamos a echar un vistazo a la lista de flujo de ejecución en conjunto.
- Se llama http.HandleFunc
- Llame HandleFunc de DefaultServeMux
- Llame Handle de DefaultServeMux
- Agregar reglas del router para mapear [cadena ] muxEntry de DefaultServeMux
- Se llama http.ListenAndServe (": 9090 " , nil )
- se instancia el servidor
- Llama ListenAndServe del Servidor
- Llama net.Listen ( " tcp" , addr ) para escuchar en el puerto .
- Iniciar un bucle, y aceptar las solicitudes en el cuerpo del bucle.
- Instanciada una Conn se empieza una goroutine para cada solicitud : ir c.serve ().
- Lee petición de datos : w , err : = c.readRequest ().
- Comprueba si el controlador está vacío, si está vacíoutiliza DefaultServeMux .
- Llama al controlador de ServeHTTP
- Ejecutar código en DefaultServeMux en este caso.
- Elije el controlador URL y ejecutar código del controlador en esta seccion: mux.handler.ServeHTTP ( w , r)
- Cómo elegir handler: A. Normas de router de verificación para esta URL. B. Llamar ServeHTTP en ese controlador, si es que existe. C. Llamar ServeHTTP de NotFoundHandler lo contrario.
- Indice
- Sección anterior: Como trabaja Go con la web
- Siguiente sección: Resumen