一、簡介
Go語言的net/http包是Go語言內置的一個HTTP處理包,使用該包可以方便地搭建HTTP伺服器或者HTTP客戶端。本文將從請求處理流程入手,對golang http包進行全面解析。
二、請求處理流程
golang http的請求處理包括:路由、處理函數、中間件等,整個處理流程如下:
http.ListenAndServe(addr string, handler http.Handler) error
ListenAndServe函數負責創建一個http.Server對象,監聽網路埠,並接受來自客戶端的請求,並分配給handler處理。handler可以是一個自定義的類型,只要實現了Handler介面。因此,我們可以使用http包默認提供的Mux類型,或者自己實現一個類型來處理請求。
type HandlerFunc func(w ResponseWriter, r *Request)
HandlerFunc是一個函數類型,用於處理請求的回調函數。函數類型需要滿足Handler介面才能作為服務處理函數傳給ListenAndServe,具體介面如下:
type Handler interface { ServeHTTP(ResponseWriter, *Request) }
該介面只有一個ServeHTTP方法,負責接收ResponseWriter和Request,其中ResponseWriter為寫回客戶端的對象,也就是Response,Request則是從客戶端發來的請求。一旦接收到請求並將函數轉發給ServeHTTP,就會按照golang默認的處理鏈路:路由 -> 處理函數 -> 中間件 -> 響應返回給客戶端。
三、路由
http包提供了一個方便的mux,或多路復用HTTP請求router,稱為http.ServeMux。通過使用mux,可以為HTTP服務提供多條處理鏈路,以便同時處理不同的URI和HTTP方法。下面是一個代碼示例
package main import ( "fmt" "net/http" ) func main() { http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello") }) http.HandleFunc("/world", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "World") }) http.ListenAndServe(":8080", nil) }
在上面的代碼中,使用了`http.HandleFunc()`函數,它接收兩個參數:路由地址和一個回調函數來處理該路由。在這個例子中,我們設置了兩條路由地址`/hello`和`/world`,並為它們各自設置了一個回調函數。最後,通過調用`http.ListenAndServe()`函數來啟動服務,並監聽埠`8080`。
四、處理函數
對於每個請求`/hello`和`/world`的回調函數,都需要一個ResponseWriter,由該函數將處理結果返回給客戶端。ResponseWriter對象有很多可用的方法,例如Write(), WriteString(), Header() 等。這些方法可以用來向客戶端發送數據,設置響應頭,或者配置響應狀態等。下面是一個處理函數的例子:
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello") })
在上面的代碼中,我們通過`http.HandleFunc()`函數為`/hello`路由地址設置了一個回調函數。這個函數在收到客戶端的請求時,將輸出`Hello`字元串。
五、中間件
golang http包的中間件是指在進入處理函數之前,對請求和響應進行預處理的插件,包括日誌、壓縮、請求超時等。中間件可以接受一些參數和可選的行為,比如跳過某些請求、或者直接終止請求處理。中間件函數需要接收一個Handler類型函數並返回一個新的Handler類型函數。以下是一個代碼示例:
func Logger(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() h.ServeHTTP(w, r) log.Printf("[%s] %s %s", r.Method, r.URL.Path, time.Since(start)) }) } func Hello(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello") } func main() { http.Handle("/hello", Logger(http.HandlerFunc(Hello))) http.ListenAndServe(":8080", nil) }
在上面的代碼中,通過實現中間件Logger函數,我們實現了對服務請求的記錄。在正式的處理函數處理完請求之後(h.ServeHTTP(w, r)),記錄請求的信息(r.Method, r.URL.Path, time.Since(start))。
六、HTTPS和TLS
HTTPS是HTTP的加密版,採用TLS協議來加密通訊數據。儘管golang不支持對HTTP的TLS,但是它提供了一個輕量級的加密TLS庫crypto/tls,可以幫助我們實現HTTPS的功能,如下面的代碼所示:
func main() { mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, "Hello, TLS") }) // 生成tls配置 cert, err := tls.LoadX509KeyPair("server.crt", "server.key") if err != nil { log.Fatal(err) } tlsConfig := &tls.Config{Certificates: []tls.Certificate{cert}} srv := &http.Server{ Addr: ":8443", Handler: mux, TLSConfig: tlsConfig, } log.Fatal(srv.ListenAndServeTLS("", "")) }
在上面的代碼中,我們創建了一個http.ServeMux對象,並為根URL`/`設置了回調函數。為了啟用TLS,我們使用tls.LoadX509KeyPair() 方法載入證書和密鑰,它們將用於加密通信。然後,我們將TLS配置傳遞給http.Server,並將其用作secureconnection。listen 並serve TLS的HTTPS處理鏈路就這樣形成了。
七、總結
本篇文章詳細介紹了golang http包的各種使用方法,包括請求處理流程、路由、處理函數、中間件、HTTPS、TLS等方面。通過掌握這些知識點,可以幫助開發人員更好地掌握Http原理,並在實際工作中運用golang http包來搭建Web伺服器及開發REST API等。
原創文章,作者:MTNB,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/150290.html