1. 程式人生 > 實用技巧 >http包詳解 1 - DefaultServeMux

http包詳解 1 - DefaultServeMux

首先我們直接呼叫2個方法就可以開啟一個http伺服器。

func hello(w http.ResponseWriter,r *http.Request) {
	w.Write([]byte("hello!\r\n"))
}
func main() {
	http.HandleFunc("/",hello)
	err := http.ListenAndServe("0.0.0.0:8889",nil)
	if err != nil {
		fmt.Println(err)
	}
}

先分析一下http.HandleFunc()這個函式。直接進入函式HandleFunc的宣告,原始碼如下:

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

這裡DefaultServeMux呼叫了HandleFunc(),引數就是傳進來的“/”HandleFunc(定義一個函式型別,就可以把函式作為引數傳入)

//2435行
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
	if handler == nil {
		panic("http: nil handler")
	}
	mux.Handle(pattern, HandlerFunc(handler))
}

HandlerFunc 是ServeMux 結構體的方法,這裡先分析HandlerFunc(handler)

,也就是把func(ResponseWriter, *Request)函式型別轉換為HandlerFunc型別(注意!是HandlerFunc,不是HandleFunc)

HandlerFunc這裡定義了一個func(ResponseWriter, *Request)的函式型別,HandlerFunc(handler)實際上就是handler本身。為什麼這麼做?

type HandlerFunc func(ResponseWriter, *Request)

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

HandlerFunc實現了ServeHTTP(w ResponseWriter, r *Request) 這個方法!!!!裡面只有一行程式碼f(w, r),也就是說實際上是呼叫handler,也就是我們一開始在http.HandleFunc("/", HandleRequest)中自己定義的函式HandleRequest。

而 HandlerFunc 實現了 ServeHTTP的方法,其實就是實現了 Handler 介面。

HandlerFunc實現Handler接口裡面的方法。跟Java裡面的介面一樣,任何實現介面的型別,都可以向上轉換為該介面型別。這就意味著HandlerFunc型別的值可以自動轉換為Handler型別的值作為引數傳進任何函式中。這很重要!回頭看看muxEntry結構體裡面的兩個變數pattern stringh Handler,不正好對應剛才傳入的引數pattern, HandlerFunc(handler)嗎!!

總結一下:

所以,HandlerFunc(handler)就是一個介面卡模式!HandlerFunc實現Handler介面,ServeHTTP方法裡面呼叫的實際上是我們一開始定義的函式HandleRequest。

這樣的一個好處就是,func(ResponseWriter,*Request) -> HandlerFunc -> Handler ,那定義的函式HandleRequest可以作為Handler型別的一個引數。呼叫Handler的ServeHTTP方法,也就是呼叫定義的函式HandleRequest。

理解完HandlerFunc(handler),再來看看整句mux.Handle(pattern, HandlerFunc(handler))

//2391
func (mux *ServeMux) Handle(pattern string, handler Handler) {
	mux.mu.Lock()
	defer mux.mu.Unlock()

	if pattern == "" {
		panic("http: invalid pattern")
	}
	if handler == nil {
		panic("http: nil handler")
	}
	if _, exist := mux.m[pattern]; exist {
		panic("http: multiple registrations for " + pattern)
	}
	if mux.m == nil {
		mux.m = make(map[string]muxEntry)
	}
	e := muxEntry{h: handler, pattern: pattern}
	mux.m[pattern] = e
	if pattern[len(pattern)-1] == '/' {
		mux.es = appendSorted(mux.es, e)
	}
	if pattern[0] != '/' {
		mux.hosts = true
	}
}

  

這裡就是把傳進來的pattern和handler儲存在muxEntry結構中,並且pattern作為key,把muxEntry裝入到DefaultServeMux的Map裡面。