91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

http.HandleFunc 解析

發布時間:2020-07-03 14:41:01 來源:網絡 閱讀:37682 作者:heyishi 欄目:編程語言

Go語言是一個神奇的語言,尤其是函數式編程,

func HandleFunc(pattern string, handler func(ResponseWriter, *Request))

就是一個典型。這個函數就是注冊默認路由。
HandleFunc 的第一個參數指的是請求路徑,第二個參數是一個函數類型,表示這個請求需要處理的事情。沒有處理復雜的邏輯,而是直接給DefaultServeMux處理,如源碼:

func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
}

DefaultServeMux 是ServeMux一個全局實例,

// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = &defaultServeMux
var defaultServeMux ServeMux

這個實例在被申明的時候初始化了,只要使用了DefaultServeMux這個變量,其實就是同一個指針而已,也就是獨一份。
DefaultServeMux.HandleFunc(pattern, handler) 函數其實也沒有做什么,直接調用路由注冊:

// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    mux.Handle(pattern, HandlerFunc(handler))
}

把自定義處理業務的函數進行路由注冊,HandlerFunc(handler) 這個處理其實是類型轉化,把函數handler func 類型轉化成HandlerFunc類型,是一個強制轉化,只要函數的參數類型一致,即可轉化。我們來看一個HandlerFunc是如何定義的:

type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

從type可以看出 HandlerFunc 就是一個自定義類型,被定義成

func(ResponseWriter, *Request)

函數。所以只要符合此標準的函數,都可以轉化成HandlerFunc,而這個函數實現了接口:

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

這個接口就是路由中,匹配的處理方法。

根據go對接口的定義,只有實現了接口的所有方法,就實現了這個接口。

我們來看是如何注冊路由的,需要理解如下兩個結構

  • ServeMux 多路路由器
  • muxEntry 具體路由
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//請求路徑
}

處邏輯源碼如下:

// Handle 根據給定的請求路勁進行注冊路由
// 如果Handle已經存在,就直接報錯
func (mux *ServeMux) Handle(pattern string, handler Handler) {
 //進行加鎖,高并發處理
    mux.mu.Lock()
    //釋放鎖
    defer mux.mu.Unlock()
 //請求路徑為空,直接報錯
    if pattern == "" {
        panic("http: invalid pattern " + pattern)
    }
    //Handle不存在,直接報錯
    if handler == nil {
        panic("http: nil handler")
    }
    //如果Handle已經存在,就直接報錯
    if mux.m[pattern].explicit {
        panic("http: multiple registrations for " + pattern)
    }
//路由表不存在,創建一個,這個路由表是一個映射MAP
//key 就是請求路徑  value是muxEntry 包含具體路由信息
    if mux.m == nil {
        mux.m = make(map[string]muxEntry)
    }
    mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern}
//如果首字母不是‘/’ 包含hostName
    if pattern[0] != '/' {
        mux.hosts = true
    }

    // Helpful behavior:
    // If pattern is /tree/, insert an implicit permanent redirect for /tree.
    // It can be overridden by an explicit registration.
    n := len(pattern)
    //如何是像/tree/ 請求注冊路由,而且/tree 還沒有注冊過
    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 直接重定向 而且注冊的注冊路徑有/tree/  /tree
        url := &url.URL{Path: path}
        mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(url.String(), StatusMovedPermanently), pattern: pattern}
    }
}

以上是對函數

func HandleFunc(pattern string, handler func(ResponseWriter, *Request))

調用過程分析

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

荆州市| 新宁县| 榆树市| 大洼县| 永州市| 桂东县| 繁昌县| 卢龙县| 积石山| 龙海市| 滨海县| 四子王旗| 平乡县| 库尔勒市| 临泽县| 东海县| 清涧县| 丽水市| 白水县| 休宁县| 临洮县| 中阳县| 贵溪市| 聊城市| 澄城县| 白银市| 五常市| 福安市| 永定县| 台安县| 日照市| 小金县| 茂名市| 越西县| 炎陵县| 罗江县| 龙岩市| 阳原县| 察隅县| 咸丰县| 丰镇市|