11

浅析Go语言http服务handler对象底层原理

 3 years ago
source link: https://segmentfault.com/a/1190000038547147
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

本文来源于: https://gobea.cn/blog/detail/15zqpwrq.html

最简单的http服务

对于golang来说,创建一个http服务是轻而易举的事情,如下,我们创建了一个非常简单的http服务,监听8899端口,只提供一个接口返回hello world

package main
import (
    "fmt"
    "net/http"
)
func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "hello world")
    })
    http.ListenAndServe(":8899", nil)
}

当你在游览器输入http://127.0.0.1:8899时,便能看到hello world的输出

http服务

对于golang的http服务,我们主要理解两个对象,:

  • Handler,它是请求的处理对象,Handler对象需要实现ServeHTTP方法,ServeHTTP执行的是我们的业务逻辑,一般我们定义的func(w http.ResponseWriter, r *http.Request)的方法需要经过http.HandlerFunc包装为Handler对象
  • ServeMux,它相当于一个路由注册器,保存的请求路径patternHandler对象的map表,通过pattern找到对应的Handler对象,然后执行Handler对象的ServeHTTP方法

简单的说,http的执行对象是handler,而要成为handler对象.则必须实现ServeHTTP方法,例如HandlerFunc实现了ServeHTTP方法,所以它也是一个handler对象

handler对象

// Handler接口
type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

// HandlerFunc实现了Handler接口
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

server从路由中找到handler对象,执行handler对象中的ServeHTTP方法,也就是说,要作为路由的Handler对象,需要实现ServeHTTP方法,有关handler如下:
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e8dc81c24cd24cbe82069d2c1d60d38f~tplv-k3u1fbpfcp-zoom-1.image

  • handler函数,具有func(w http.ResponseWriter, r *http.Requests)签名的函数,需要经过HandlerFunc函数包装,否则不能作为路由的Handler对象,
  • handler处理函数,经过HandlerFunc结构包装的handler函数,HandlerFunc实现了ServeHTTP接口方法的函数
  • handler对象,实现了Handler接口ServeHTTP方法的结构

注册路由ServeMux

type ServeMux struct {
    mu    sync.RWMutex
    m     map[string]muxEntry
    hosts bool 
}

type muxEntry struct {
    explicit bool
    h        Handler
    pattern  string
}

// ServeMux也拥有ServeHTTP方法,也就说ServeMux实现了Handler接口,即ServeMuX其实也是一个Handler对象,不过ServeMux的ServeHTTP方法不是用来处理request和respone,而是用来找到路由注册的handler
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
    if r.RequestURI == "*" {
        if r.ProtoAtLeast(1, 1) {
            w.Header().Set("Connection", "close")
        }
        w.WriteHeader(StatusBadRequest)
        return
    }
    h, _ := mux.Handler(r)
    h.ServeHTTP(w, r)
}

如上,ServeMux.m保存了路由规则pattern以及对应的Handler处理对象,另外ServeMux也拥有ServeHTTP方法,也就说ServeMux实现了Handler接口,即ServeMuX其实也是一个Handler对象,不过ServeMux的ServeHTTP方法不是用来处理request和respone,而是用来找到路由注册的handler

package main

import (
    "fmt"
    "net/http"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "hello world")
    })
    mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "hello world")
    })
    http.ListenAndServe(":8899", mux)
}

Server

http.ListenAndServe(":8899",mux)
// 等价于
serv := &http.Server{
        Addr:    ":8899",
        Handler: mux,
    }
serv.ListenAndServe()

http.ListenAndServe源码如下:

func ListenAndServe(addr string, handler Handler) error {
    server := &Server{Addr: addr, Handler: handler}
    return server.ListenAndServe()
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK