http 路由实现原理

HTTP 路由组件负责将 HTTP 请求交到对应的函数处理(或者是对应的 struct 的方法),路由在框架中相当于一个事件处理器,而这个事件包括:

  • 用户请求的路径(path),参数
  • HTTP 请求方法(GET|POST|PUT|DELETE|PATCH)

路由器就是根据用户请求的事件信息转发到相应的处理函数(控制层)

默认的路由实现

func fooHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
}

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

路由的思想主要集中在两点:

  • 添加路由的信息

    DefultserveMux.Handle(pattern string, handler Handler)

  • 根据用户请求转发要执行的函数

路由信息的添加:

http.Handlehttp.HandleFuncDefultserveMux.Handle(pattern string, handler Handler)map[string]muxEntry

函数处理:

http.DefaultServeMux
for k, v := range mux.m {
	if !pathMatch(k, path) {
		continue
	}
	if h == nil || len(k) > n {
		n = len(k)
		h = v.h
	}
}

自定义路由器实现

基于以上的理解,我们可以自定义一个路由处理器:

package main

import (
	"fmt"
	"net/http"
)

type MyHandle struct {

}

func (handle *MyHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.URL.Path {
	case "/hello":
		sayHello(w,r)
		return
	case "/hi":
		sayHi(w,r)
		return
	}
	http.NotFound(w,r)
	return
}

func sayHello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello Golang!")
}

func sayHi(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hi Golang!")
}

func main() {
	handle := MyHandle{}
	http.ListenAndServe(":9000", &handle)
}
go run main.go