Go中處理請求
1 概述
Go 語言 HTTP 伺服器,在啟動監聽並處理接收的請求時,會將請求相關資料封裝成 http.Request
物件,同時作為引數傳遞到請求處理器中。處理器函式的第二個引數就是對 http.Request
物件的一個引用,示例程式碼為:
func main() { // 設定 路由 http.HandleFunc("/", IndexAction)· // 開啟監聽 log.Fatal(http.ListenAndServe(":8888", nil)) } func IndexAction(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<h1 align="center">來自小韓說課的問候</h1>`)) }
2 http.Request
結構
type Request struct { Method string // 請求方法,"" 預設為 GET URL *url.URL // URL 物件引用 Protostring // 協議 "HTTP/1.0" ProtoMajor int// 1 ProtoMinor int// 0 Header Header // 請求頭物件 Body io.ReadCloser // 請求主體物件 GetBody func() (io.ReadCloser, error) // 獲取請求主體的拷貝函式,用於客戶端場景 ContentLength int64 // 請求主體長度 TransferEncoding []string // 轉換編碼 Close bool // 是否在結束後關閉連線 Host string // 主機 Form url.Values // 解析好的 form 資料,同時包含 URL 中的 QueryString,呼叫 ParseForm() 後生效 PostForm url.Values // 解析好的 POST、PUT、PATCH 的 form 資料,呼叫 ParseForm() 後生效 MultipartForm *multipart.Form // 解析好的 multipart form,包含上傳檔案 Trailer Header // 指定請求傳送後的附加頭資訊 RemoteAddr string // 請求來源地址 RequestURI string // 請求行中未修改的請求URI,通常使用 URL 欄位代替 TLS *tls.ConnectionState // TLS 狀態資訊物件 Cancel <-chan struct{} // 指示客戶端請求可取消的閉包通道 Response *Response // 重定向到引發本次請求的響應物件 ctx context.Context // 伺服器與客戶端的上下文 }
3 請求方式
func IndexAction(w http.ResponseWriter, r *http.Request) { log.Print(r.Method) } // GET
4 請求引數
通過 URL.Query()
方法可以獲取查詢字串值 URL.values
物件,是一個對映結構。物件上的 .Get(key string)
方法獲取 key 對應的第一個值。
// http://localhost:8888/?name=Hank func IndexAction(w http.ResponseWriter, r *http.Request) { log.Print(r.URL.Query()) log.Print(r.URL.Query()["name"]) log.Print(r.URL.Query().Get("name")) } // map[name:[Hank]] // [Hank] // Hank
除此之外,請求值物件 URL.Values
還支援:
func (v Values) Set(key, value string) func (v Values) Add(key, value string) func (v Values) Del(key string) func (v Values) Encode() string
5 請求頭
請求物件的 Header
屬性可以訪問到請求頭資訊。是對映結構,提供了 Get(key string)
方法獲取 key 對應的第一個值。
// http://localhost:8888/ func IndexAction(w http.ResponseWriter, r *http.Request) { log.Print(r.Header) log.Print(r.Header["User-Agent"]) log.Print(r.Header.Get("User-Agent")) } // map[User-Agent:[Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36] Accept:[text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8] Accept-Encoding:[gzip, deflate, br] Accept-Language:[zh-CN,zh;q=0.9,en;q=0.8] Connection:[keep-alive] Cache-Control:[max-age=0] Upgrade-Insecure-Requests:[1]] // [Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36] // Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
除此之外, Header
物件還支援:
func (h Header) Set(key, value string) func (h Header) Add(key, value string) func (h Header) Del(key string) func (h Header) Write(w io.Writer) error
6 請求 URL
Request.URL
引用的是 url.URL
結構體型別,利用該物件可以獲取 URL 相關資訊。其定義結構為:
type URL struct { Schemestring // 協議 Opaquestring// 編碼資料 User*Userinfo // username 和 password 資訊 Hoststring// 主機,格式為 host:port Pathstring// 路徑(相對路徑會省略前導斜錢) RawPathstring// 編碼 path (see EscapedPath method) ForceQuery bool// 追加查詢 ('?') 即使 RawQuery 為空 RawQuerystring// 編碼查詢字串, 不包括 '?' Fragmentstring// 引用片段, 不包括 '#' }
典型的URL格式為: scheme://[userinfo@]host/path[?query][#fragment]
。
注意,伺服器端程式會獲取 URI 資訊而客戶端資訊會獲取 URL 資訊。
示例:
// http://localhost:8888/path/to/script.html func IndexAction(w http.ResponseWriter, r *http.Request) { log.Print(r.URL.Path) } // /path/to/script.html