Golang net/http知識講解

如下是對net/http的學習。瀏覽器

Go 語言中處理 HTTP 請求主要跟兩個東西相關:ServeMux 和 Handler。 ServrMux 本質上是一個 HTTP 請求路由器(或者叫多路複用器,Multiplexor)。它把收到的請求與一組預先定義的 URL 路徑列表作對比,而後在匹配到路徑的時候調用關聯的處理器(Handler)。服務器

處理器(Handler)負責輸出HTTP響應的頭和正文。任何知足了http.Handler接口的對象均可做爲一個處理器。通俗的說,對象只要有個以下簽名的ServeHTTP方法便可:閉包

ServeHTTP(http.ResponseWriter, *http.Request)

Go 語言的 HTTP 包自帶了幾個函數用做經常使用處理器,好比FileServer,NotFoundHandler 和 RedirectHandler。咱們從一個簡單具體的例子開始:函數

package main

import (
	"log"
	"net/http"
)

func main() {
	mux := http.NewServeMux()

	rh := http.RedirectHandler("http://www.baidu.com", 307)
	mux.Handle("/foo", rh)

	log.Println("Listening...")
	http.ListenAndServe(":3000", mux)
}

快速地過一下代碼:學習

在 main 函數中咱們只用了 http.NewServeMux 函數來建立一個空的 ServeMux。 而後咱們使用 http.RedirectHandler 函數建立了一個新的處理器,這個處理器會對收到的全部請求,都執行307重定向操做到 http://www.baidu.com。 接下來咱們使用 ServeMux.Handle 函數將處理器註冊到新建立的 ServeMux,因此它在 URL 路徑/foo 上收到全部的請求都交給這個處理器。 最後咱們建立了一個新的服務器,並經過 http.ListenAndServe 函數監聽全部進入的請求,經過傳遞剛纔建立的 ServeMux來爲請求去匹配對應處理器。code

而後在瀏覽器中訪問 http://localhost:3000/foo 你應該能發現請求已經成功的重定向了。orm

明察秋毫的你應該能注意到一些有意思的事情:ListenAndServer 的函數簽名是 ListenAndServe(addr string, handler Handler) ,可是第二個參數咱們傳遞的是個 ServeMux。對象

咱們之因此能這麼作,是由於 ServeMux 也有 ServeHTTP 方法,所以它也是個合法的 Handler。接口

對我來講,將 ServerMux 用做一個特殊的Handler是一種簡化。它不是本身輸出響應而是將請求傳遞給註冊到它的其餘 Handler。這乍一聽起來不是什麼明顯的飛躍 - 但在 Go 中將 Handler 鏈在一塊兒是很是廣泛的用法。ip

自定義處理器(Custom Handlers)

真正的重點是咱們有一個對象(本例中就是個timerHandler結構體,可是也能夠是一個字符串、一個函數或者任意的東西),咱們在這個對象上實現了一個 ServeHTTP(http.ResponseWriter, *http.Request) 簽名的方法,這就是咱們建立一個處理器所需的所有東西。

package main

import (
	"log"
	"net/http"
	"time"
)

type timeHandler struct {
	format string
}

func (th *timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	tm := time.Now().Format(th.format)
	w.Write([]byte("The time is : " + tm))
}

func main() {
	mux := http.NewServeMux()

	rh := http.RedirectHandler("http://www.baidu.com", 307)
	th := &timeHandler{format: time.RFC1123}

	mux.Handle("/a", rh)
	mux.Handle("/time", th)

	log.Println("Listening.....")
	http.ListenAndServe(":3000", mux)

}

將函數做爲處理器

http.HandlerFunc()可以讓一個常規函數做爲一個Handler接口條件

func timeHandler(w http.ResponseWriter, r *http.Request) {
	tm := time.Now().Format(time.RFC1123)
	w.Write([]byte("the time is : " + tm))
}

func main() {
	mux := http.NewServeMux()

	rh := http.RedirectHandler("http://www.baidu.com", 307)
	th := http.HandlerFunc(timeHandler)

	mux.Handle("/a", rh)
	mux.Handle("/time", th)

	log.Println("Listening.....")
	http.ListenAndServe(":3000", mux)

}

更爲便捷的方式:ServerMux.HandlerFunc 方法

func main() {
	mux := http.NewServeMux()

	mux.HandleFunc("/time", timeHandler)

	log.Println("Listening...")
	http.ListenAndServe(":3000", mux)
}

若是方法中須要參數,則須要使用閉包,將變量帶入:

//demo1
 func timeHandler(format string) http.Handler{
	fn:=func(w http.ResponseWriter,r *http.Request){
		tm:=time.Now().Format(format)
		w.Write([]byte("The time is : "+tm))
	}

	 return http.HandlerFunc(fn)
 }
 //demo2
 func timeHandler(format string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		tm := time.Now().Format(format)
		w.Write([]byte("The time is: " + tm))
	})
}
//demo3
func timeHandler(format string) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		tm := time.Now().Format(format)
		w.Write([]byte("The time is: " + tm))
	}
}

更爲便利的DefaultServeMux

net/http 包提供了一組快捷方式來配合 DefaultServeMux:http.Handle 和 http.HandleFunc。這些函數與咱們以前看過的相似的名稱的函數功能同樣,惟一的不一樣是他們將處理器註冊到 DefaultServerMux ,而以前咱們是註冊到本身建立的 ServeMux。

此外,ListenAndServe在沒有提供其餘的處理器的狀況下(也就是第二個參數設成了 nil),內部會使用 DefaultServeMux。

所以,做爲最後一個步驟,咱們使用 DefaultServeMux 來改寫咱們的 timeHandler應用:

func timeHandler(format string) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		tm := time.Now().Format(format)
		w.Write([]byte("The time is : " + tm))
	}

	return http.HandlerFunc(fn)
}

func main() {
	/* mux := http.NewServeMux()

	rh := http.RedirectHandler("http://www.baidu.com", 307)
	th := timeHandler(time.RFC1123)

	mux.Handle("/a", rh)
	mux.Handle("/time", th)

	log.Println("Listening.....")
	http.ListenAndServe(":3000", mux)
	*/

	var format string = time.RFC1123

	th := timeHandler(format)

	http.Handle("/time", th)

	log.Println("listening....")

	http.ListenAndServe(":3000", nil)
}
相關文章
相關標籤/搜索