http包详解 1 - http包初识
首先,熟悉http协议的都知道,http协议是基于TCP实现的。
http服务器的工作方式大概就是监听socket端口,接受连接,获取到请求,处理请求,返回响应。
所以,对应的会有几个部分
-
Request:用户请求的信息。post、get、url等这些信息
-
Response: 返回给客户端的信息
-
Conn: 用户每次的连接请求
-
Handler:处理请求和返回信息的逻辑处理
我们直接调用2个方法就可以开启一个http服务器。
func hello(w http.ResponseWriter,r *http.Request) { w.Write([]byte("hello!\r\n")) } func main() { http.HandleFunc("/",hello) err := http.ListenAndServe("0.0.0.0:8889",nil) if err != nil { fmt.Println(err) } }
//2451行
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
对于DefaultServeMux在源代码中的声明如下
type ServeMux struct { mu sync.RWMutex m map[string]muxEntry hosts bool // whether any patterns contain hostnames } type muxEntry struct { explicit bool h Handler pattern string } // NewServeMux allocates and returns a new ServeMux. func NewServeMux() *ServeMux { return &ServeMux{m: make(map[string]muxEntry)} } // DefaultServeMux is the default ServeMux used by Serve. var DefaultServeMux = NewServeMux()
这里DefaultServeMux调用了HandleFunc(),参数就是传进来的“/”
和HandleFunc
(定义一个函数类型,就可以把函数作为参数传入)
//2435行 func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { if handler == nil { panic("http: nil handler") } mux.Handle(pattern, HandlerFunc(handler)) }
type HandlerFunc func(ResponseWriter, *Request) // ServeHTTP calls f(w, r). func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) }
而 HandlerFunc 实现了 ServeHTTP的方法,其实就是实现了 Handler 接口。
总结一下:
所以,HandlerFunc(handler)
//2391 func (mux *ServeMux) Handle(pattern string, handler Handler) { mux.mu.Lock() defer mux.mu.Unlock() if pattern == "" { panic("http: invalid pattern") } if handler == nil { panic("http: nil handler") } if _, exist := mux.m[pattern]; exist { panic("http: multiple registrations for " + pattern) } if mux.m == nil { mux.m = make(map[string]muxEntry) } e := muxEntry{h: handler, pattern: pattern} mux.m[pattern] = e if pattern[len(pattern)-1] == '/' { mux.es = appendSorted(mux.es, e) } if pattern[0] != '/' { mux.hosts = true } }
这里的代码直接关注到第17行和37行
由于37行的代码是经过判断后进入if的语句,所以别扣细节,直接关注第17行。
mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern}
都是赋值语句,基本逻辑都是为DefaultServeMux里面的map赋值。
总结一下
这里就是把传进来的pattern和handler保存在muxEntry结构中,并且pattern作为key,把muxEntry装入到DefaultServeMux的Map里面。
至此,第一个关键的函数http.HandleFunc("/", HandleRequest)
就分析完了,就是把当前的参数"/", HandleRequest
保存在http包里面的默认的一个ServeMux结构中的map中,简单来说就是保存当前路由和自己定义的那个处理函数。虽然理顺思路感觉挺简单,但是不得不赞叹设计得实在太妙了