畅远数码|万字手撕Go http源码server.go( 五 )
package mainimport ("fmt""log""net/http""sync")type countHandler struct {mu sync.Mutex // guards nnint}func (h *countHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {h.mu.Lock()defer h.mu.Unlock()h.n++fmt.Fprintf(w, "count is %d\n", h.n)}func main() {http.Handle("/count", new(countHandler))log.Fatal(http.ListenAndServe(":8080", nil))}复制代码HandlerHandler是接口
Handler定义在go package的官网文档中是这样定义Handler的“Handler响应HTTP请求” , 理解成中文就是“处理程序” 。
Handler是一个接口 , 定义在net/http原生包中:
type Handler interface {ServeHTTP(ResponseWriter, *Request)}复制代码对于任何实现了ServeHTTP方法的都属于Handler 。
Handler性质1.Handler只能用来读取request的body , 而不能修改请求
2.先读取body , 然后再写入resp
3.事实上在真正的开发过程中 , 我们不太会经常使用Handler , 因为net/http给我们提供了更方便的HandleFunc()函数 , 而这个函数可以让我们直接将一个函数作为handler , 在这里handler是函数类型而非此Handle接口 , 这种实现较实现ServeHTTP()来说更加方便 。
Handler用于处理请求并给予响应 , 更严格地说 , 用来读取请求体、并将请求对应的响应字段(respones header)写入ResponseWriter中 , 然后返回
HandlerFunchttp还提供了HandlerFunc类 , 和HandleFunc()函数仅有一字之差
HandlerFunc本质是一个适配器函数 , 这个类在内部实现了ServeHTTP()函数 , 因此这个类本质上是一个Handler类型
HandlerFunc()定义HandlerFunc(f) 是调用f函数的处理程序
函数原型:
type HandlerFunc func(ResponseWriter, *Request)复制代码源码// 调用默认ServerMux的HandleFunc方法func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {DefaultServeMux.HandleFunc(pattern, handler)}// 把方法handler转换成HandlerFunc类型 , 即实现了Handler接口;再执行Handle方法func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {mux.Handle(pattern, HandlerFunc(handler))}// 路由器注册一个handler给指定的partternfunc (mux *ServeMux) Handle(pattern string, handler Handler) {....}复制代码执行HandleFunc()其实就是为某一规则的请求注册处理器 。
Handler/HandlerFunc区别Handler是一个接口
HandlerFunc是Handler类型 , 是一个适配器函数
Handle()/HandleFunc()区别HandleFunc()和Handle()都是调用DefaultServeMux对应的方法 , 而DefaultServeMux是ServeMux的实例 , ServeMux实现了Handler接口 。 事实上 , HandleFunc()最终还是会调用Handle方法 , 之前也提到过了:
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {...mux.Handle(pattern, HandlerFunc(handler))}复制代码路由注册过程路由注册过程是由mux结构体内的两个方法mux.Handle()和mux.HandleFunc()实现的
mux.Handle()
之前大致了解了函数体 , 路由注册过程主要由ServeMux 结构体内的Handle()方法实现的 , 如果该路由已经存在在路由表内 , 则会引发Panic
ServeMux结构体内的Handle() 方法大致上干了这样几件事:
1.检查路由合法性 , 若不合法则给出报错信息 , 报错信息multiple registrations for /xxx 就属于路由重复注册而引发的问题
2.若多路复用器中没有路由表 , 则创建路由表
3.若路由合法则创建路由条目muxEntry添加至路由表中
推荐阅读
- 英雄科技聊数码|蔡崇信有实力买下篮网,那身价3200亿的马云,能买下几支NBA球队
- 搜狐新闻|准大学生数码三件套如何选?这些元气好物值得种草
- 数码鲜蜂|三星大秀肌肉!这个透明手机如何?
- 数码科技大爆炸|台积电断供华为芯片开启倒计时!已不足10天:华为多位高管表态
- 海外网|菅义伟计划对厚生劳动省进行改革 创设"数码厅"
- 数码实验室|《飞速骑行4》2021年推出PS5和XboxSeriesX版
- 老实人数码|取代苹果XR系列,不支持5G网络,iPhone12s真机疑似被曝光
- 畅远数码|马云曾提出的4大预言,已经实现3个,网友:最后一个才是关键
- 神说要唱歌|数码宝贝大冒号14话解读 虫王对决 偷学战斗龙卷风的超比多兽
- 畅远数码|欧洲大量5G基站被烧毁!原因让人啼笑皆非
