畅远数码|万字手撕Go http源码server.go( 六 )
4.若路由最后一个字符带有"/" , 则按照自定义排序函数appendSorted()的规则定位索引、插入并排序(尽管我对此函数的执行效率充满疑惑) , 返回排序后的数组 。
5.若路由的首字母不为"/" , 则包含主机名
mux.HandleFunc()
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {if handler == nil {panic("http: nil handler")}mux.Handle(pattern, HandlerFunc(handler))}复制代码Helpful behavior在之前版本的server.go中 , 注册函数mux.Handle是存在一些辅助行为的 , 当你将路由路径设置为/tree/时 , Helpful behavior会隐式永久的帮你将/tree注册到注册表中 , 当然也可以显式指定路由进行覆盖 , 在对/tree/进行访问时 , /tree的handler会自动将请求重定向到/tree/:
状态代码: 301 / Moved Permanently复制代码在现在server.go中 , ServeMux结构体内维护了一个es类型的数组 , 就是从长到短记录最后一个字母是'/'路由字符串的
在使用mux.match()对路由path进行匹配的时候(详情见“路由查找过程”) , 首先查找路由表 , 当路由表中不存在该路由时 , 遍历es数组 , 匹配其最大长度:
// Find a handler on a handler map given a path string.// Most-specific (longest) pattern wins.func (mux *ServeMux) match(path string) (h Handler, pattern string) {// Check for exact match first.v, ok := mux.m[path]if ok {return v.h, v.pattern}// Check for longest valid match.mux.es contains all patterns// that end in / sorted from longest to shortest.for _, e := range mux.es {if strings.HasPrefix(path, e.pattern) {return e.h, e.pattern}}return nil, ""}复制代码服务请求过程参考官网的文档 , 我们可以使用golang原生的库net/http来实现一个简单的web路由示例:
// serve.gopackage mainimport ("fmt""net/http")func main() {http.HandleFunc("/", HelloWorld)http.ListenAndServe(":8080", nil)}func HelloWorld(w http.ResponseWriter, r *http.Request) {fmt.Fprint(w, "Hello World")}复制代码其实主函数中只有两个方法 , HandleFunc()和ListenAndServe() , 整个请求响应的执行流程如下:
- 注册路由过程:首先调用HandleFunc():调用了默认复用器DefaultServeMux的HandleFunc() , 调用了DefaultServeMux的Handle , 往DefaultServeMux的map[string]muxEntry中增加对应的handler和路由规则 。
- 实例化server并调用server.ListenAndServe() , 调用net.Listen("tcp", addr)监听端口 。 启动一个for循环 , 在循环体中Accept请求
- 对每个请求实例化一个Conn , 并且开启一个goroutine为这个请求进行服务go c.serve()
- 读取每个请求的内容w, err := c.readRequest()
- 进入serveHandler.ServeHTTP若有自己实现的mux则使用自己的mux 。 判断handler是否为空 , 如果没有设置handler(此例子中为nil handler) , handler就设置为DefaultServeMux
- 调用handler的ServeHttp , 进入到DefaultServeMux.ServeHttp
- 根据request选择匹配handler , 并且进入到这个handler的ServeHTTP
http.ListenAndServe(":8080", nil)复制代码传入handler是nil , 则使用默认复用器DefaultServeMux , 调用HandleFunc时 , 就是向默认复用器注册了handler// ServeHTTP dispatches the request to the handler whose// pattern most closely matches the request URL.func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {if r.RequestURI == "*" {if r.ProtoAtLeast(1, 1) {w.Header().Set("Connection", "close")}w.WriteHeader(StatusBadRequest)return}h, _ := mux.Handler(r)h.ServeHTTP(w, r)}复制代码
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 英雄科技聊数码|蔡崇信有实力买下篮网,那身价3200亿的马云,能买下几支NBA球队
- 搜狐新闻|准大学生数码三件套如何选?这些元气好物值得种草
- 数码鲜蜂|三星大秀肌肉!这个透明手机如何?
- 数码科技大爆炸|台积电断供华为芯片开启倒计时!已不足10天:华为多位高管表态
- 海外网|菅义伟计划对厚生劳动省进行改革 创设"数码厅"
- 数码实验室|《飞速骑行4》2021年推出PS5和XboxSeriesX版
- 老实人数码|取代苹果XR系列,不支持5G网络,iPhone12s真机疑似被曝光
- 畅远数码|马云曾提出的4大预言,已经实现3个,网友:最后一个才是关键
- 神说要唱歌|数码宝贝大冒号14话解读 虫王对决 偷学战斗龙卷风的超比多兽
- 畅远数码|欧洲大量5G基站被烧毁!原因让人啼笑皆非
