Golang實(shí)現(xiàn)HTTP編程請求和響應(yīng)
請求:
HTTP 請求報文由請求行、請求頭部、空行、請求包體4個部分組成,如下圖所示:

請求行:
請求行由方法字段、URL 字段 和HTTP 協(xié)議版本字段 3個部分組成,他們之間使用空格隔開。常用的 HTTP 請求方法有 GET、POST。
GET:
- 當(dāng)客戶端要從服務(wù)器中讀取某個資源時,使用GET 方法。GET 方法要求服務(wù)器將URL 定位的資源放在響應(yīng)報文的數(shù)據(jù)部分,回送給客戶端,即向服務(wù)器請求某個資源。
- 使用GET方法時,請求參數(shù)和對應(yīng)的值附加在 URL 后面,利用一個問號(“?”)代表URL 的結(jié)尾與請求參數(shù)的開始,傳遞參數(shù)長度受限制,因此GET方法不適合用于上傳數(shù)據(jù)。
- 通過GET方法來獲取網(wǎng)頁時,參數(shù)會顯示在瀏覽器地址欄上,因此保密性很差。
POST:
- 當(dāng)客戶端給服務(wù)器提供信息較多時可以使用POST 方法,POST 方法向服務(wù)器提交數(shù)據(jù),比如完成表單數(shù)據(jù)的提交,將數(shù)據(jù)提交給服務(wù)器處理。
- GET 一般用于獲取/查詢資源信息,POST 會附帶用戶數(shù)據(jù),一般用于更新資源信息。POST 方法將請求參數(shù)封裝在HTTP 請求數(shù)據(jù)中,而且長度沒有限制,因?yàn)镻OST攜帶的數(shù)據(jù),在HTTP的請求正文中,以名稱/值的形式出現(xiàn),可以傳輸大量數(shù)據(jù)。
請求頭:
請求頭部為請求報文添加了一些附加信息,由“名/值”對組成,每行一對,名和值之間使用冒號分隔。請求頭部通知服務(wù)器有關(guān)于客戶端請求的信息,典型的請求頭有:
| 請求頭 | 含義 |
|---|---|
| User-Agent | 請求的瀏覽器類型 |
| Accept | 客戶端可識別的響應(yīng)內(nèi)容類型列表,星號“ * ”用于按范圍將類型分組,用“ / ”指示可接受全部類型,用“ type/* ”指示可接受 type 類型的所有子類型 |
| Accept-Language | 客戶端可接受的自然語言 |
| Accept-Encoding | 客戶端可接受的編碼壓縮格式 |
| Accept-Charset | 可接受的應(yīng)答的字符集 |
| Host | 請求的主機(jī)名,允許多個域名同處一個IP 地址,即虛擬主機(jī) |
| connection | 連接方式(close或keepalive) |
| Cookie | 存儲于客戶端擴(kuò)展字段,向同一域名的服務(wù)端發(fā)送屬于該域的cookie |
空行:
最后一個請求頭之后是一個空行,發(fā)送回車符和換行符,通知服務(wù)器以下不再有請求頭。
請求包體:
請求包體不在GET方法中使用,而在POST方法中使用。POST方法適用于需要客戶填寫表單的場合。與請求包體相關(guān)的最常使用的是包體類型Content-Type和包體長度Content-Length。
響應(yīng):
響應(yīng)報文格式說明
HTTP 響應(yīng)報文由狀態(tài)行、響應(yīng)頭部、空行、響應(yīng)包體4個部分組成,如下圖所示:

狀態(tài)行:
狀態(tài)行由 HTTP 協(xié)議版本字段、狀態(tài)碼和狀態(tài)碼的描述文本3個部分組成,他們之間使用空格隔開。
狀態(tài)碼:狀態(tài)碼由三位數(shù)字組成,第一位數(shù)字表示響應(yīng)的類型,常用的狀態(tài)碼有五大類如下所示:
| 狀態(tài)碼 | 含義 |
|---|---|
| 1xx | 表示服務(wù)器已接收了客戶端請求,客戶端可繼續(xù)發(fā)送請求 |
| 2xx | 表示服務(wù)器已成功接收到請求并進(jìn)行處理 |
| 3xx | 表示服務(wù)器要求客戶端重定向 |
| 4xx | 表示客戶端的請求有非法內(nèi)容 |
| 5xx | 表示服務(wù)器未能正常處理客戶端的請求而出現(xiàn)意外錯誤 |
常見的狀態(tài)碼舉例:
| 狀態(tài)碼 | 含義 |
|---|---|
| 200 OK | 客戶端請求成功 |
| 400 Bad Request | 請求報文有語法錯誤 |
| 401 Unauthorized | 未授權(quán) |
| 403 Forbidden | 服務(wù)器拒絕服務(wù) |
| 404 Not Found | 請求的資源不存在 |
| 500 Internal Server Error | 服務(wù)器內(nèi)部錯誤 |
| 503 Server Unavailable | 服務(wù)器臨時不能處理客戶端請求(稍后可能可以) |
響應(yīng)頭可能包括:
| 響應(yīng)頭 | 含義 |
|---|---|
| Location Location | 響應(yīng)報頭域用于重定向接受者到一個新的位置 |
| Server Server | 響應(yīng)報頭域包含了服務(wù)器用來處理請求的軟件信息及其版本 |
| Vary | 指示不可緩存的請求頭列表 |
| Connection | 連接方式 |
空行:
最后一個響應(yīng)頭部之后是一個空行,發(fā)送回車符和換行符,通知服務(wù)器以下不再有響應(yīng)頭部。
響應(yīng)包體:
服務(wù)器返回給客戶端的文本信息
響應(yīng)報文格式:
要想獲取響應(yīng)報文,必須先發(fā)送請求報文給web服務(wù)器。服務(wù)器收到并解析瀏覽器(客戶端)發(fā)送的請求報文后,借助http協(xié)議,回復(fù)相對應(yīng)的響應(yīng)報文??梢杂胣et/http包,創(chuàng)建一個最簡單的服務(wù)器,給瀏覽器回發(fā)送響應(yīng)包。首先注冊處理函數(shù)http.HandleFunc(),設(shè)置回調(diào)函數(shù)handler。而后綁定服務(wù)器的監(jiān)聽地址http.ListenAndserve()。這個服務(wù)器啟動后,當(dāng)有瀏覽器發(fā)送請求,回調(diào)函數(shù)被調(diào)用,會向?yàn)g覽器回復(fù)“hello world”作為網(wǎng)頁內(nèi)容。當(dāng)然,是按照http協(xié)議的格式進(jìn)行回復(fù)。
HTTP服務(wù)端實(shí)現(xiàn):
Go語言標(biāo)準(zhǔn)庫內(nèi)建提供了net/http包,涵蓋了HTTP客戶端和服務(wù)端的具體實(shí)現(xiàn)。使用net/http包,我們可以很方便地編寫HTTP客戶端或服務(wù)端的程序。
package main
import (
"fmt"
"net/http"
)
func main() {
/**
注冊回調(diào)函數(shù),該回調(diào)函數(shù)會在服務(wù)器被訪問時自動被調(diào)用
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
pattern:訪問服務(wù)器文件位置
handler:回調(diào)函數(shù)名,函數(shù)必須是ResponseWriter, *Request類型作為參數(shù)
*/
http.HandleFunc("/itzhuzhu", myHandlerFunc)
/**
綁定服務(wù)器監(jiān)聽地址
func ListenAndServe(addr string, handler Handler) error
addr:要監(jiān)聽的地址
handler:回調(diào)函數(shù),為空則調(diào)用系統(tǒng)默認(rèn)的回調(diào)函數(shù)
*/
http.ListenAndServe("127.0.0.1:8000", nil)
}
/**
ResponseWriter:寫給客戶端的數(shù)據(jù)內(nèi)容
Request:從客戶端讀取到的數(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客戶端實(shí)現(xiàn):
客戶端模擬瀏覽器發(fā)送請求:
package main
import (
"fmt"
"net"
"os"
)
func main() {
// 客戶端連接服務(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ā)送請求報文
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中。可以使用它提供的Read方法來獲取數(shù)據(jù)內(nèi)容。保存至切片緩沖區(qū)中,拼接成一個完整的字符串來查看。
結(jié)束的時候,需要調(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)
}
到此這篇關(guān)于Golang實(shí)現(xiàn)HTTP編程請求和響應(yīng)的文章就介紹到這了,更多相關(guān)Golang HTTP編程請求和響應(yīng)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go數(shù)據(jù)結(jié)構(gòu)之HeapMap實(shí)現(xiàn)指定Key刪除堆
這篇文章主要給大家介紹了Go語言數(shù)據(jù)結(jié)構(gòu)之HeapMap實(shí)現(xiàn)指定Key刪除堆,通過使用Go語言中的container/heap包,我們可以輕松地實(shí)現(xiàn)一個優(yōu)先級隊列,文中有詳細(xì)的代碼示例講解,需要的朋友可以參考下2023-07-07
Golang打印復(fù)雜結(jié)構(gòu)體兩種方法詳解
在?Golang?語言開發(fā)中,我們經(jīng)常會使用結(jié)構(gòu)體類型,如果我們使用的結(jié)構(gòu)體類型的變量包含指針類型的字段,我們在記錄日志的時候,指針類型的字段的值是指針地址,將會給我們?debug?代碼造成不便2022-10-10
基于Go+WebSocket實(shí)現(xiàn)實(shí)時通信功能
在互聯(lián)網(wǎng)應(yīng)用程序中,實(shí)時通信是一種非常重要的功能,WebSocket 是一種基于 TCP 的協(xié)議,它允許客戶端和服務(wù)器之間進(jìn)行雙向通信,本文將介紹如何使用 Golang 創(chuàng)建單獨(dú)的 WebSocket 會話,以實(shí)現(xiàn)實(shí)時通信功能,需要的朋友可以參考下2023-10-10

