您好,登錄后才能下訂單哦!
本文小編為大家詳細(xì)介紹“Golang如何實(shí)現(xiàn)HTTP編程請(qǐng)求和響應(yīng)”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“Golang如何實(shí)現(xiàn)HTTP編程請(qǐng)求和響應(yīng)”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來(lái)學(xué)習(xí)新知識(shí)吧。
請(qǐng)求:
HTTP 請(qǐng)求報(bào)文由請(qǐng)求行、請(qǐng)求頭部、空行、請(qǐng)求包體4個(gè)部分組成,如下圖所示:
請(qǐng)求行:
請(qǐng)求行由方法字段、URL 字段 和HTTP 協(xié)議版本字段 3個(gè)部分組成,他們之間使用空格隔開(kāi)。常用的 HTTP 請(qǐng)求方法有 GET、POST。
GET:
當(dāng)客戶(hù)端要從服務(wù)器中讀取某個(gè)資源時(shí),使用GET 方法。GET 方法要求服務(wù)器將URL 定位的資源放在響應(yīng)報(bào)文的數(shù)據(jù)部分,回送給客戶(hù)端,即向服務(wù)器請(qǐng)求某個(gè)資源。
使用GET方法時(shí),請(qǐng)求參數(shù)和對(duì)應(yīng)的值附加在 URL 后面,利用一個(gè)問(wèn)號(hào)(“?”)代表URL 的結(jié)尾與請(qǐng)求參數(shù)的開(kāi)始,傳遞參數(shù)長(zhǎng)度受限制,因此GET方法不適合用于上傳數(shù)據(jù)。
通過(guò)GET方法來(lái)獲取網(wǎng)頁(yè)時(shí),參數(shù)會(huì)顯示在瀏覽器地址欄上,因此保密性很差。
POST:
當(dāng)客戶(hù)端給服務(wù)器提供信息較多時(shí)可以使用POST 方法,POST 方法向服務(wù)器提交數(shù)據(jù),比如完成表單數(shù)據(jù)的提交,將數(shù)據(jù)提交給服務(wù)器處理。
GET 一般用于獲取/查詢(xún)資源信息,POST 會(huì)附帶用戶(hù)數(shù)據(jù),一般用于更新資源信息。POST 方法將請(qǐng)求參數(shù)封裝在HTTP 請(qǐng)求數(shù)據(jù)中,而且長(zhǎng)度沒(méi)有限制,因?yàn)镻OST攜帶的數(shù)據(jù),在HTTP的請(qǐng)求正文中,以名稱(chēng)/值的形式出現(xiàn),可以傳輸大量數(shù)據(jù)。
請(qǐng)求頭:
請(qǐng)求頭部為請(qǐng)求報(bào)文添加了一些附加信息,由“名/值”對(duì)組成,每行一對(duì),名和值之間使用冒號(hào)分隔。請(qǐng)求頭部通知服務(wù)器有關(guān)于客戶(hù)端請(qǐng)求的信息,典型的請(qǐng)求頭有:
請(qǐng)求頭 | 含義 |
---|---|
User-Agent | 請(qǐng)求的瀏覽器類(lèi)型 |
Accept | 客戶(hù)端可識(shí)別的響應(yīng)內(nèi)容類(lèi)型列表,星號(hào)“ * ”用于按范圍將類(lèi)型分組,用“ / ”指示可接受全部類(lèi)型,用“ type/* ”指示可接受 type 類(lèi)型的所有子類(lèi)型 |
Accept-Language | 客戶(hù)端可接受的自然語(yǔ)言 |
Accept-Encoding | 客戶(hù)端可接受的編碼壓縮格式 |
Accept-Charset | 可接受的應(yīng)答的字符集 |
Host | 請(qǐng)求的主機(jī)名,允許多個(gè)域名同處一個(gè)IP 地址,即虛擬主機(jī) |
connection | 連接方式(close或keepalive) |
Cookie | 存儲(chǔ)于客戶(hù)端擴(kuò)展字段,向同一域名的服務(wù)端發(fā)送屬于該域的cookie |
空行:
最后一個(gè)請(qǐng)求頭之后是一個(gè)空行,發(fā)送回車(chē)符和換行符,通知服務(wù)器以下不再有請(qǐng)求頭。
請(qǐng)求包體:
請(qǐng)求包體不在GET方法中使用,而在POST方法中使用。POST方法適用于需要客戶(hù)填寫(xiě)表單的場(chǎng)合。與請(qǐng)求包體相關(guān)的最常使用的是包體類(lèi)型Content-Type和包體長(zhǎng)度Content-Length。
響應(yīng):
響應(yīng)報(bào)文格式說(shuō)明
HTTP 響應(yīng)報(bào)文由狀態(tài)行、響應(yīng)頭部、空行、響應(yīng)包體4個(gè)部分組成,如下圖所示:
狀態(tài)行:
狀態(tài)行由 HTTP 協(xié)議版本字段、狀態(tài)碼和狀態(tài)碼的描述文本3個(gè)部分組成,他們之間使用空格隔開(kāi)。
狀態(tài)碼:狀態(tài)碼由三位數(shù)字組成,第一位數(shù)字表示響應(yīng)的類(lèi)型,常用的狀態(tài)碼有五大類(lèi)如下所示:
狀態(tài)碼 | 含義 |
---|---|
1xx | 表示服務(wù)器已接收了客戶(hù)端請(qǐng)求,客戶(hù)端可繼續(xù)發(fā)送請(qǐng)求 |
2xx | 表示服務(wù)器已成功接收到請(qǐng)求并進(jìn)行處理 |
3xx | 表示服務(wù)器要求客戶(hù)端重定向 |
4xx | 表示客戶(hù)端的請(qǐng)求有非法內(nèi)容 |
5xx | 表示服務(wù)器未能正常處理客戶(hù)端的請(qǐng)求而出現(xiàn)意外錯(cuò)誤 |
常見(jiàn)的狀態(tài)碼舉例:
狀態(tài)碼 | 含義 |
---|---|
200 OK | 客戶(hù)端請(qǐng)求成功 |
400 Bad Request | 請(qǐng)求報(bào)文有語(yǔ)法錯(cuò)誤 |
401 Unauthorized | 未授權(quán) |
403 Forbidden | 服務(wù)器拒絕服務(wù) |
404 Not Found | 請(qǐng)求的資源不存在 |
500 Internal Server Error | 服務(wù)器內(nèi)部錯(cuò)誤 |
503 Server Unavailable | 服務(wù)器臨時(shí)不能處理客戶(hù)端請(qǐng)求(稍后可能可以) |
響應(yīng)頭可能包括:
響應(yīng)頭 | 含義 |
---|---|
Location Location | 響應(yīng)報(bào)頭域用于重定向接受者到一個(gè)新的位置 |
Server Server | 響應(yīng)報(bào)頭域包含了服務(wù)器用來(lái)處理請(qǐng)求的軟件信息及其版本 |
Vary | 指示不可緩存的請(qǐng)求頭列表 |
Connection | 連接方式 |
空行:
最后一個(gè)響應(yīng)頭部之后是一個(gè)空行,發(fā)送回車(chē)符和換行符,通知服務(wù)器以下不再有響應(yīng)頭部。
響應(yīng)包體:
服務(wù)器返回給客戶(hù)端的文本信息
響應(yīng)報(bào)文格式:
要想獲取響應(yīng)報(bào)文,必須先發(fā)送請(qǐng)求報(bào)文給web服務(wù)器。服務(wù)器收到并解析瀏覽器(客戶(hù)端)發(fā)送的請(qǐng)求報(bào)文后,借助http協(xié)議,回復(fù)相對(duì)應(yīng)的響應(yīng)報(bào)文??梢杂胣et/http包,創(chuàng)建一個(gè)最簡(jiǎn)單的服務(wù)器,給瀏覽器回發(fā)送響應(yīng)包。首先注冊(cè)處理函數(shù)http.HandleFunc(),設(shè)置回調(diào)函數(shù)handler。而后綁定服務(wù)器的監(jiān)聽(tīng)地址http.ListenAndserve()。這個(gè)服務(wù)器啟動(dòng)后,當(dāng)有瀏覽器發(fā)送請(qǐng)求,回調(diào)函數(shù)被調(diào)用,會(huì)向?yàn)g覽器回復(fù)“hello world”作為網(wǎng)頁(yè)內(nèi)容。當(dāng)然,是按照http協(xié)議的格式進(jìn)行回復(fù)。
HTTP服務(wù)端實(shí)現(xiàn):
Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)內(nèi)建提供了net/http包,涵蓋了HTTP客戶(hù)端和服務(wù)端的具體實(shí)現(xiàn)。使用net/http包,我們可以很方便地編寫(xiě)HTTP客戶(hù)端或服務(wù)端的程序。
package main import ( "fmt" "net/http" ) func main() { /** 注冊(cè)回調(diào)函數(shù),該回調(diào)函數(shù)會(huì)在服務(wù)器被訪問(wèn)時(shí)自動(dòng)被調(diào)用 func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) pattern:訪問(wèn)服務(wù)器文件位置 handler:回調(diào)函數(shù)名,函數(shù)必須是ResponseWriter, *Request類(lèi)型作為參數(shù) */ http.HandleFunc("/itzhuzhu", myHandlerFunc) /** 綁定服務(wù)器監(jiān)聽(tīng)地址 func ListenAndServe(addr string, handler Handler) error addr:要監(jiān)聽(tīng)的地址 handler:回調(diào)函數(shù),為空則調(diào)用系統(tǒng)默認(rèn)的回調(diào)函數(shù) */ http.ListenAndServe("127.0.0.1:8000", nil) } /** ResponseWriter:寫(xiě)給客戶(hù)端的數(shù)據(jù)內(nèi)容 Request:從客戶(hù)端讀取到的數(shù)據(jù)內(nèi)容 */ func myHandlerFunc(w http.ResponseWriter, r *http.Request) { w.Write([]byte("ResponseWriter Test")) fmt.Println("Header:", r.Header) fmt.Println("URL:", r.URL) fmt.Println("Method:", r.Method) fmt.Println("Host:", r.Host) fmt.Println("RemoteAddr:", r.RemoteAddr) fmt.Println("Body:", r.Body) }
HTTP客戶(hù)端實(shí)現(xiàn):
客戶(hù)端模擬瀏覽器發(fā)送請(qǐng)求:
package main import ( "fmt" "net" "os" ) func main() { // 客戶(hù)端連接服務(wù)器 dial, err := net.Dial("tcp", "127.0.0.1:8000") errFunction("net.Dial err:", err) defer dial.Close() // 模擬瀏覽器 requstHttpHeader := "GET /itzhuzhu HTTP/1.1\r\nHost:127.0.0.1:8000\r\n\r\n" // 給服務(wù)器發(fā)送請(qǐng)求報(bào)文 dial.Write([]byte(requstHttpHeader)) buf := make([]byte, 1024) // 讀取服務(wù)器的回復(fù) read, err := dial.Read(buf) errFunction("dial.Read err:", err) fmt.Println( string(buf[:read])) } func errFunction(describe string, err error) { if err != nil { fmt.Println(describe, err) os.Exit(1) } }
服務(wù)器發(fā)送的響應(yīng)包體被保存在Body中??梢允褂盟峁┑腞ead方法來(lái)獲取數(shù)據(jù)內(nèi)容。保存至切片緩沖區(qū)中,拼接成一個(gè)完整的字符串來(lái)查看。
結(jié)束的時(shí)候,需要調(diào)用Body中的Close()方法關(guān)閉io。
package main import ( "fmt" "net/http" ) func main() { // 使用Get方法獲取服務(wù)器響應(yīng)包數(shù)據(jù) resp, err := http.Get("http://www.baidu.com") if err != nil { fmt.Println("Get err:", err) return } defer resp.Body.Close() // 獲取服務(wù)器端讀到的數(shù)據(jù) fmt.Println("Status = ", resp.Status) // 狀態(tài) fmt.Println("StatusCode = ", resp.StatusCode) // 狀態(tài)碼 fmt.Println("Header = ", resp.Header) // 響應(yīng)頭部 fmt.Println("Body = ", resp.Body) // 響應(yīng)包體 buf := make([]byte, 4096) // 定義切片緩沖區(qū),存讀到的內(nèi)容 var result string // 獲取服務(wù)器發(fā)送的數(shù)據(jù)包內(nèi)容 for { n, err := resp.Body.Read(buf) // 讀body中的內(nèi)容。 if n == 0 { fmt.Println("Body.Read err:", err) break } result += string(buf[:n]) // 累加讀到的數(shù)據(jù)內(nèi)容 } // 打印從body中讀到的所有內(nèi)容 fmt.Println("result = ", result) }
讀到這里,這篇“Golang如何實(shí)現(xiàn)HTTP編程請(qǐng)求和響應(yīng)”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過(guò)才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。