Go Web学习 -标准库 net/http 使用

Golang
393
0
0
2022-08-31

实现一个简单的 http 服务

package main

import (
    "fmt" 
    "log" 
    "net/http"
)

func main() {
    http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
        fmt.Fprint(rw, "hello word")
    })
    log.Fatal(http.ListenAndServe(":9777", nil))
}

原理解析:

在main()函数的第一行,我们通过http.HandleFunc定义了路由为”/“的响应函数,这个响应函数,接受传来的Request,并对Response做一定的处理即写入HelloWorld然后直接返回给浏览器。然后便可以直接调用http.ListenAndServe来监听本地的9777端口,便可以直接在浏览器上看到Hello World。

HandleFunc 的实现

func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
}

DefaultServeMux是http包中的全局变量,它的原型是ServeMux这个结构体。

type ServeMux struct {
    mu    sync.RWMutex        //保护m
    m     map[string]muxEntry //URL:Handler映射表
    hosts bool
}
type muxEntry struct {
    explicit bool
    h        Handler
    pattern  string
}

ServerMux 这个结构体的 HandelFunc 方法:

// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    mux.Handle(pattern, HandlerFunc(handler))  //又调用了mux.Handle
}

而 mux.Handle 就比较简单了,就是将 func(http.ResponseWriter,*http.Request)转换为 http.Handler 然后放入mux的map中。而http.Handler是一个接口类型,二者是如何转换的?不妨看看 mux.HandleFunc

type HandlerFunc func(ResponseWriter, *Request) 
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

上面这个函数,其实就是一个实现了 http.Handler 接口的类型,该类型底层基础类型就是 func(ResponseWriter, *Request),我们知道在go语言中除了 指针与接口 其他基础类型也是可以定义方法的,标准库定义这个一个类型,为的就是将 普通func(ResponseWriter, *Request) 适配到 http.Handler接口

ListenAndServe这个方法

// ListenAndServe always returns a non-nil error.
func ListenAndServe(addr string, handler Handler) error {
    server := &Server{Addr: addr, Handler: handler}
    return server.ListenAndServe()
}

源码中可以看到该方法会将传入进来的addr参数和handler送给Server这个结构体,从而新建一个server然后调用这个server的ListenAndServe方法,处理流程大致如下:

server监听到有新链接进来,创建一个goroutine来处理新链接

在goroutine中,将请求和响应分别封装为 http.Request和http.ResponseWriter对象。然后用这两个对象作为函数参数调用 server.Handler.serveHTTP(…), 而server.Handler 即为我们传入的 http.ServeMux 对象,而http.ServeMux对象的serveHTTP方法,我们都没有碰过,里面到底做了什么?

http.ServeMux对象的serveHTTP方法做的事,其实就是根据 http.Request对象中的URL 在自己的map中查找对应的Handler(这个又是我们在step1中添加的),然后执行。

绕了一大圈,简单来说就是 每当有新请求进来,server都会为我们新建一个goroutine,并在其中根据请求URL调用 我们在创建server之前添加的 URL:Handler映射表(通过server中的http.Handler字段混入)中的相应URL的Handler.

net/http包中几个重要的类型:

http.ServeMux: 建立URL:Handler映射表

http.Server: 运行HTTP Server

http.Request: 封装客户端HTTP请求数据

http.ResponseWriter: 用来构造服务器端HTTP响应数据

http.Handler: URL处理程序必须实现的接口