前言
net/http 库的服务端实现
上两篇文章介绍了 http 客户端的实现,这篇文章看一下服务端的实现
服务端
使用 net/http 库可以快速搭建HTTP服务,HTTP服务端主要包含两部分:
- 注册处理器:
net/http.HandleFunc函数用于注册处理器 - 监听端口:
net/http.ListenAndServe用于处理请求
package main
import (
"fmt"
"net/http"
)
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello World")
}
func main() {
http.HandleFunc("/hello", hello)
http.ListenAndServe(":8080", nil)
}
注册处理器
直接调用net/http.HandleFunc可以注册路由和处理函数:
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
我们调用http.HandleFunc("/hello", hello)注册路径处理函数,这里将路径/hello的处理函数设置为hello。处理函数的类型必须是:
func (http.ResponseWriter, *http.Request)
它调用HTTP服务起的DefaultServeMux处理请求,DefaultServeMux本质是ServeMux:
type ServeMux struct {
mu sync.RWMutex // 读写锁,保证并发安全,注册处理器时会加写锁做保护
m map[string]muxEntry // 路由规则,一个string对应一个mux实体,这里的string就是注册的路由表达式
es []muxEntry // slice of entries sorted from longest to shortest.
hosts bool // whether any patterns contain hostnames
}
**mu**:需要加读写锁保证并发安全,注册处理器时会加写锁保证写map的数据正确性,这个map就是pattern和handler;**m**:存储路由规则,key就是pattern,value是muEntry实体,muEntry实体中包含:pattern和handler**es**:存储的也是muxEntry实体,因为我们使用map存储路由和handler的对应关系,所以只能索引静态路由,并不支持[path_param],所以这块的作用是当在map中没有找到匹配的路由时,会遍历这个切片进行前缀匹配,这个切片按照路由长度进行排序;**hosts**:这个也是用来应对特殊case,如果我们注册的路由没有以/开始,那么就认为我们注册的路由包含host,所以路由匹配时需要加上host;
func (mux *ServeMux) Handle(pattern string, handler Handler

最低0.47元/天 解锁文章
3099

被折叠的 条评论
为什么被折叠?



