<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      我在這里-> silenceper.com

      Go的http包中默認路由匹配規則

      # 一、執行流程 首先我們構建一個簡單http server: ```go package main import ( "log" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hello world")) }) log.Fatal(http.ListenAndServe(":8080", nil)) } ``` 使用`http://127.0.0.1:8080/` 就可以看到輸出了 通過跟蹤http.go包代碼,可以發現執行流程基本如下: - 1.創建一個`Listener`監聽`8080`端口 - 2.進入`for`循環并Accept請求,沒有請求則處于阻塞狀態 - 3.接收到請求,并創建一個conn對象,放入goroutine處理(實現高并發關鍵) - 4.解析請求來源信息獲得請求路徑等重要信息 - 5.請求ServerHTTP方法,已經通過上一步獲得了ResponseWriter和Request對象 ```go func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) { //此handler即為http.ListenAndServe 中的第二個參數 handler := sh.srv.Handler if handler == nil { //如果handler為空則使用內部的DefaultServeMux 進行處理 handler = DefaultServeMux } if req.RequestURI == "*" && req.Method == "OPTIONS" { handler = globalOptionsHandler{} } //這里就開始處理http請求 //如果需要使用自定義的mux,就需要實現ServeHTTP方法,即實現Handler接口。 handler.ServeHTTP(rw, req) } ``` - 6.進入DefaultServeMux中的邏輯就是根據請求path在map中匹配查找handler,并交由handler處理 >http請求處理流程更多信息可以參考[《Go Web 編程 》3.3 Go如何使得Web工作](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/03.3.md) # 二、DefaultServeMux 路由匹配規則 先看幾個路由規則: ```go package main import ( "log" "net/http" ) func main() { //規則1 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hello world")) }) //規則2 http.HandleFunc("/path/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("pattern path: /path/ ")) }) //規則3 http.HandleFunc("/path/subpath", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("pattern path: /path/subpath")) }) log.Fatal(http.ListenAndServe(":8080", nil)) } ``` 情景一: 訪問:`http://127.0.0.1:8080/` 返回:`hello world` 情景二: 訪問:`http://127.0.0.1:8080/path` 返回:`pattern path: /path/ ` 情景三: 訪問:`http://127.0.0.1:8080/path/subpath/` 返回:`pattern path: /path/ ` 情景四: 訪問:`http://127.0.0.1:8080/hahaha/` 返回:`hello world` 先說明一些規則吧,再看代碼是怎么實現的: 1.如果匹配路徑中后帶有`/`,則會自動增加一個匹配規則不帶`/`后綴的,并跳轉轉到`path/`,解釋了情景二的場景,為什么匹配到的`/path/` 2.我設置了這么多規則為什么規則一可以通用匹配未設置的路由信息,而且又不影響已經存在路由, 內部是怎么實現的? ## 2.1 添加路由規則 先看兩個struct,這是存放默認路由規則的: ```go type ServeMux struct { mu sync.RWMutex //處理并發,增加讀寫鎖 m map[string]muxEntry //存放規則map,key即為設置的path hosts bool // whether any patterns contain hostnames(是否包含host) } type muxEntry struct { explicit bool //是否完全匹配 h Handler//相應匹配規則的handler pattern string//匹配路徑 } ``` 通過跟蹤`http.HandleFunc`定位到如下代碼,正是往上面兩個`struct`中增加規則: ```go func (mux *ServeMux) Handle(pattern string, handler Handler) { mux.mu.Lock() defer mux.mu.Unlock() if pattern == "" { panic("http: invalid pattern " + pattern) } if handler == nil { panic("http: nil handler") } //如果已經匹配到了則panic if mux.m[pattern].explicit { panic("http: multiple registrations for " + pattern) } //增加一個新的匹配規則 mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern} //根據path的第一個字母判斷是否有host if pattern[0] != '/' { mux.hosts = true } //!!這里看清楚 就是實現了情景二的情況 ,看判斷條件 n := len(pattern) if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit{ // If pattern contains a host name, strip it and use remaining // path for redirect. path := pattern if pattern[0] != '/' { // In pattern, at least the last character is a '/', so // strings.Index can't be -1. path = pattern[strings.Index(pattern, "/"):] } url := &url.URL{Path: path} mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(url.String(), StatusMovedPermanently), pattern: pattern} } } ``` 上面有個`Helpful behavior`的注釋行為,就是實現了情景二的情況,他是判斷如果匹配的路徑中最后含有`/`,并且之前也不存在添加去除反斜杠的規則的話,就自動給他增加一個301的跳轉指向`/path/` ## 2.2 查找路由規則 路由規則的查找就是從`ServeMux `中的map去匹配查找的,的到這個handler并執行,只是會有一些處理機制,比如怎么樣確保訪問`/path/subpath`的時候是先匹配`/path/subpath`而不是匹配`/path/`呢? 當一個請求過來的時候,跟蹤到了`mux.match`方法: >過程`mux.ServerHTTP`->`mux.Handler`->`mux.handler`->`mux.match` ```go func (mux *ServeMux) match(path string) (h Handler, pattern string) { var n = 0 for k, v := range mux.m { if !pathMatch(k, path) { continue } //如果匹配到了一個規則,并沒有馬上返回handler,而且繼續匹配并且判斷path的長度是否是最長的,這是關鍵!!! if h == nil || len(k) > n { n = len(k) h = v.h pattern = v.pattern } } return } ``` 1.這里就解釋了為什么設置的精確的path是最優匹配到的,因為它是根據path的長度判斷。 當然也就解釋了為什么`/`可以匹配所有(看`pathMatch`函數就知道了,`/`是匹配所有的,只是這是最后才被匹配成功) 2.得到了處理請求的handler,再調用`h.ServeHTTP(w, r)`,去執行相應的handler方法。 等一下,handler中哪里有`ServeHTTP`這個方法?? 因為在調用 `http.HandleFunc`的時候已經將自定義的handler處理函數,強制轉為`HandlerFunc`類型的,就擁有了`ServeHTTP`方法: ```go type HandlerFunc func(ResponseWriter, *Request) // ServeHTTP calls f(w, r). func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) } ``` `f(w,r)`就實現了handler的執行。 > 關注"學點程序"公眾號,了解更多干貨內容 ![學點程序](https://silenceper.oss-cn-beijing.aliyuncs.com/qrcode/qr_code_study_program_430.jpg )
      posted on 2020-01-22 11:07  seekrays2  閱讀(863)  評論(0)    收藏  舉報

      產品:seekrays

      主站蜘蛛池模板: 亚洲成色精品一二三区| 亚洲a免费| 日韩有码中文字幕国产| 国产成人8X人网站视频| 快好爽射给我视频| 亚洲国产成人无码av在线播放 | Y111111国产精品久久久| 最新亚洲人成网站在线观看| 五月开心六月丁香综合色啪 | 国内不卡不区二区三区| 亚洲国产欧美在线看片一国产| 婷婷精品国产亚洲av在线观看| 99热精品国产三级在线观看| 日韩人妻不卡一区二区三区| 国产欧美另类精品久久久| 国产免费午夜福利蜜芽无码| 中文字幕亚洲人妻一区| 国产成人精品av| 亚洲国产成人久久综合一区77| 日韩中文字幕人妻精品| 布尔津县| 亚洲国产精品综合久久20| 国产精品一区二区三区四区| 精品无码国产自产拍在线观看蜜 | av永久免费网站在线观看| 国产AV福利第一精品| 丁香五月亚洲综合在线国内自拍| 国产亚洲综合区成人国产| 丰满少妇呻吟高潮经历| 久久天天躁狠狠躁夜夜躁2012| 蜜臀91精品国产高清在线| 丰满熟女人妻一区二区三| 人妻性奴波多野结衣无码| 人人人澡人人肉久久精品| 成人3D动漫一区二区三区| 2020国产成人精品视频| 亚洲AV无码一二区三区在线播放| 香蕉久久夜色精品国产成人 | 国产精品久久精品| 毛多水多高潮高清视频| 中文国产不卡一区二区|