golang http server探究(上)

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

在golang當中啟動一個http服務非常簡單,比如:

http.HandFunc("/",func(w http.RequestWriter,r *http.Request){   io.WriteString(w,"hello world!")})http.ListenAndServer(":9090")   //outprint hello world!

為什麼 訪問 localhost:9090 就能列印出 Hello world 呢?這背後究竟發生了呢?下面我們就一層一層揭開這個面紗! 1 追蹤 http.HandFunc函數,發現它調用了 :

DefaultServeMux.HandleFunc(pattern, handler)

DefaultServeMux實際是ServerMux(路由)的一個預設被初始化的一個結構,所以這個http.handfunc 最底層調用的是ServeMux.HandleFunc。在看這個函數之前,我們先看看,我們的第一個重要的結構體:ServerMux(路由)

type ServeMux struct {    mu    sync.RWMutex   //並發鎖    m     map[string]muxEntry  //路由map    hosts bool // whether any patterns contain hostnames}type muxEntry struct {    explicit bool    h        Handler   //當前路由的處理器    pattern  string   //路由字串  eq:/hello}

分析:一個ServeMux 通過一個私人的muxEntry map儲存了所有的路由。每個muxEntry 裡面都包含有一個h(handler)處理器,用來出來這個路由的邏輯。

回到上面的ServerMux.HandleFunc。我們繼續追蹤這個函數,發現它調用了ServeMux.Handle()這個方法:

ServeMux.Handle(pattern string, handler Handler)//mux.Handle(pattern, HandlerFunc(handler))  調用

ServeMux.Handle 這個函數 需要兩個參數,一個參數 路由的path路徑,另一個是一個handler(擁有這個路徑具體處理邏輯的函數),這個handler 是什麼東西呢?

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

Hander就是一個擁有ServerHTTP函數的類型。回到上面的ServeMux.Handle(path,HandleFunc(handle)),我們發現,從一開始,我們傳進去的只是一個具體的函數,就是:

func(w http.RequestWriter,r *http.Request){   io.WriteString(w,"hello world!")}

這個函數,但是它怎麼就是變成 Handler了呢?我們看看HandlerFunc這個東西?這個東西比較有意思。

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

HandlerFunc 是一個函數 類型,同時它有一個ServeHTTP這個方法,也就是它已經實現了 Handler這個介面,所以 可以用在所有以Handler為參數的地方,也就是可以用在 ServeMux.Handle() 的第2 個參數位置上。同時在HandFunc.ServeHTTP 內部它調用的 是HandFunc 這個函數(調用它自己),換句話說,就是一個具體的函數,通過HandleFunc 這個類型轉換以後就變成了Handle類型。這個技巧我們可以學習一下。

下面,我們看看,ServeMux.Handle 內部的具體實現:

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")    }    if mux.m[pattern].explicit {        panic("http: multiple registrations for " + pattern)    }    mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern}        //    if pattern[0] != '/' {        mux.hosts = true    }    n := len(pattern)    if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit {        path := pattern        if pattern[0] != '/' {            path = pattern[strings.Index(pattern, "/"):]        }        url := &url.URL{Path: path}        mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(url.String(), StatusMovedPermanently), pattern: pattern}    }}

這裡簡單說 就是 把 path,和對應的handle添加到ServerMux.muxEntry 裡面。到這裡,我們對路由的分析就完成了。現在我們在回顧一下:

下次我們 分析一下 Server。

關注程式猿公眾帳號:

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.