Skip to content

Latest commit

 

History

History
135 lines (99 loc) · 5.04 KB

File metadata and controls

135 lines (99 loc) · 5.04 KB

3.4 Obteniendo el paquete http

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.

goroutine en Conn

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 .

ServeMux personalizado

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)
}

GO flujo de ejecución del código

Vamos a echar un vistazo a la lista de flujo de ejecución en conjunto.

  • Se llama http.HandleFunc
    1. Llame HandleFunc de DefaultServeMux
    2. Llame Handle de DefaultServeMux
    3. Agregar reglas del router para mapear [cadena ] muxEntry de DefaultServeMux
  • Se llama http.ListenAndServe (": 9090 " , nil )
    1. se instancia el servidor
    2. Llama ListenAndServe del Servidor
    3. Llama net.Listen ( " tcp" , addr ) para escuchar en el puerto .
    4. Iniciar un bucle, y aceptar las solicitudes en el cuerpo del bucle.
    5. Instanciada una Conn se empieza una goroutine para cada solicitud : ir c.serve ().
    6. Lee petición de datos : w , err : = c.readRequest ().
    7. Comprueba si el controlador está vacío, si está vacíoutiliza DefaultServeMux .
    8. Llama al controlador de ServeHTTP
    9. Ejecutar código en DefaultServeMux en este caso.
    10. Elije el controlador URL y ejecutar código del controlador en esta seccion: mux.handler.ServeHTTP ( w , r)
    11. 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.

Enlaces