Dive Into HTTP Router in Golang
golang默认的http router
我们从Golang的http router开始学习,学习下面几点:
分析什么是router
解析Go内部是如何实现router
分析为什么Go内部已经有了router后还会出现各种个样的router,他们提供了哪些Go内部router不能完成的功能
我们如何实现一个自定义的router
我们如何在自定义的router上面完成我们想要的各种功能:高效率、Middleware、异常捕获及处理、如何简单的完成JSON类型的返回等等
DEMO
首先看golang默认的http router是如何工作的。
看一个简单的例子,
package main
import (
"fmt"
"html"
"log"
"net/http"
)
func fooHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
}
func main() {
http.HandleFunc("/foo", fooHandler)
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
log.Fatal(http.ListenAndServe(":8080", nil))
}
运行:
go run main.go
调用:
curl http://localhost:8080/foo
# Hello, "/foo"
curl http://localhost:8080/bar
# Hello, "/bar"
curl http://localhost:8080/
# 404 page not found
现象
注册了两个函数用于处理请求
/foo
:通过fooHandler
进行处理/bar
:通过func(w http.ResponseWriter, r *http.Request)
进行处理
HTTP service启动并监听
:8080
端口,等待客户端请求客户端使用
curl
发起HTTP GET请求时,Golang根据调用的接口路径调用了不同的函数进行处理
原理
至关重要的是:如何把客户端的请求与服务器中HTTP处理函数关联起来,这也是路由器的工作。
解析
查看http.ListenAndServe(":8080", nil)
函数的内部,
方法http.ListenAndServe
原型为:
// ListenAndServe listens on the TCP network address addr and then calls
// Serve with handler to handle requests on incoming connections.
// Accepted connections are configured to enable TCP keep-alives.
//
// The handler is typically nil, in which case the DefaultServeMux is used.
//
// ListenAndServe always returns a non-nil error.
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
ListenAndServe
从注释上可以看到主要做了两个工作:
监听(listen on)TCP的地址
调用
handler
的Serve
来处理连接进来的请求
如果handler
,即第2个入参,为nil
,则使用DefaultServeMux
。
那么,DefaultServeMux又是什么呢?
// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = &defaultServeMux
var defaultServeMux ServeMux
从代码上可以看到是ServeMux
类型的对象,
这个类型的定义及重要解释为,
// ServeMux is an HTTP request multiplexer.
// It matches the URL of each incoming request against a list of registered
// patterns and calls the handler for the pattern that
// most closely matches the URL.
// ...
type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
hosts bool // whether any patterns contain hostnames
}
ServeMux是一个HTTP的multiplexer,翻译过来就是:数据选择器或者叫多路复用器。
它的作用就是当来了一个HTTP请求后,根据请求的URL匹配服务器端已经注册好的各种处理函数,找到一个最合适的进行处理。
剩下的注释就是解释Golang自带的默认路由器是如何匹配各种情况的,暂时先跳过。