Go標準庫之Requests的介紹與基本使用
一、介紹
官方文檔 DOC: https://pkg.go.dev/github.com/levigross/grequests
Github: http://github.com/levigross/grequests
Python中的Requests
庫非常強大,所以Go開發(fā)者模仿Python的Requests
庫,由此誕生了Grequests
庫。Grequests
提供了一系列便利功能,使得發(fā)送HTTP請求變得簡單高效。下面就是Grequests
在Golang中實現(xiàn)的一些關鍵特性:
- 響應序列化:
Grequests
支持將HTTP響應內(nèi)容序列化為JSON和XML格式,讓處理API響應時更為方便。 - 文件上傳和下載:提供了便捷的方式來上傳和下載文件,無需復雜的配置。
- HTTP動詞支持:支持廣泛的HTTP動詞,包括GET、HEAD、POST、PUT、DELETE、PATCH以及OPTIONS,可以覆蓋大多數(shù)HTTP請求場景。
二、安裝
要開始使用Grequests庫,你需要先在你的Go環(huán)境中安裝它。通過下面的命令即可完成安裝:
go get -u github.com/levigross/grequests
三、導入
在安裝完Grequests后,你可以通過import語句把它引入到你的Go代碼中:
import "github.com/levigross/grequests"
四、基本使用
4.1 發(fā)送GET 請求
下面是一個發(fā)送GET請求的示例,其中演示了如何獲取HTTP響應并打印出來:
func Get() { resp, err := grequests.Get("http://127.0.0.1:8080/book/", nil) if err != nil { log.Fatalln("Unable to make request: ", err) } if !resp.Ok { log.Fatalln("請求超時!") } // 解析響應的JSON數(shù)據(jù) var data []map[string]interface{} if err := resp.JSON(&data); err != nil { log.Fatalln("Unable to parse JSON response: ", err) } fmt.Println(data) }
上面的代碼首先使用Get
方法發(fā)送GET請求,然后檢查是否有錯誤發(fā)生。如果沒有錯誤,就可以通過resp.Json()
方法獲取響應的文本內(nèi)容。
4.2 POST請求發(fā)送JSON數(shù)據(jù)
在下面的例子中,我們創(chuàng)建了一個map對象來保存我們想要發(fā)送的JSON數(shù)據(jù)。然后我們通過ROption
創(chuàng)建了一個請求選項對象,并在其中指定了JSON為發(fā)送的數(shù)據(jù)類型。最后,我們調(diào)用Post
方法來發(fā)送請求:
func Post() { postData := map[string]string{ "id": "1", "name": "Go入門到進階", } geq := &grequests.RequestOptions{ JSON: postData, } resp, err := grequests.Post("http://127.0.0.1:8080/book/create", geq) if err != nil { log.Fatalln("Unable to make request: ", err) } fmt.Println(resp.String()) }
下面是代碼的逐行解釋:
postData := map[string]string{"id": "1", "name": "Go入門到進階"}
這里定義了一個map[string]string
類型的變量postData
,其中包含了兩個鍵值對,分別是"id"和"name",它們的值分別是"1"和"Go入門到進階"。
geq := &grequests.RequestOptions{JSON: postData}
這里創(chuàng)建了一個grequests.RequestOptions
類型的變量geq
。grequests.RequestOptions
是一個結構體,用于配置HTTP請求的各種選項,如URL、方法、頭信息、數(shù)據(jù)等。在這個例子中,我們通過JSON
字段將postData
作為JSON數(shù)據(jù)傳遞給POST請求。
resp, err := grequests.Post("http://127.0.0.1:8080/book/create", geq)
這里調(diào)用grequests.Post
函數(shù)發(fā)起一個POST請求。http://127.0.0.1:8080/book/create
是請求的目標URL,而geq
是請求的配置選項。grequests.Post
函數(shù)會返回一個Response
對象和一個可能的錯誤。
if err != nil { log.Fatalln("Unable to make request: ", err) }
如果grequests.Post
函數(shù)調(diào)用時發(fā)生錯誤,這個條件塊會執(zhí)行。log.Fatalln
函數(shù)會打印錯誤消息并退出程序。
fmt.Println(resp.String())
如果請求成功,這個條件塊會執(zhí)行。resp.String()
方法會返回響應體的字符串表示,然后使用fmt.Println
函數(shù)將其打印到標準輸出。
總的來說,這段代碼的作用是向本地服務器(假設在127.0.0.1:8080
上)的/book/create
路徑發(fā)送一個POST請求,請求體是JSON格式的數(shù)據(jù),包含一個ID和書名。如果請求成功,它會打印出服務器的響應。如果請求失敗,它會打印出錯誤信息并退出程序。
4.3 Post 文件上傳
文件上傳同樣簡單。你可以通過RequestOptions
指定文件:
func UploadFile() { // 允許您通過指定磁盤上的位置來創(chuàng)建FileUpload結構片 // 打開要上傳的文件 file, err := os.Open("./go.mod") if err != nil { log.Fatalln("Unable to open file: ", err) } defer file.Close() // 創(chuàng)建FileUpload結構片 ro := &grequests.RequestOptions{ Files: []grequests.FileUpload{{ FileName: "1.txt", // 上傳后的文件名稱 FieldName: "file", // 上傳文件對應字段 FileContents: file, // 使用文件內(nèi)容作為FileContents }}, } // 發(fā)送POST請求 resp, err := grequests.Post("http://127.0.0.1:8080/book/upload/", ro) if err != nil { log.Fatalln("Unable to make request: ", err) } fmt.Println(resp.String()) }
在上述代碼中,我們創(chuàng)建了一個FileUpload
結構,通過FileName
、FieldName
和FileContents
來指定我們要上傳的文件詳情。
4.4 GoRequests 使用代理
gorequest
代理,下面是一個簡單的例子,需要把Proxies
中的URL添加為*url.URL
代理:
func Proxy() { // 代理服務器 const proxyServer = "http-pro.xxx.com:9010" // 代理隧道驗證信息 const proxyUser = "xxxxxxxxx" const proxyPass = "xxxxxxxxx" // 初始化代理URL proxyUrl, _ := url.Parse("http://" + proxyUser + ":" + proxyPass + "@" + proxyServer) // 創(chuàng)建請求選項 ro := &grequests.RequestOptions{ Proxies: map[string]*url.URL{ "http": proxyUrl, }, Headers: map[string]string{ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36", }, } // 發(fā)起GET請求 resp, err := grequests.Get("http://www.example.com", ro) if err != nil { fmt.Println("Error:", err) return } // 打印響應狀態(tài)碼 fmt.Println("Status code:", resp.StatusCode) // 打印響應體 fmt.Println("Response:", resp.String()) }
下面是代碼的逐行解釋:
// 代理服務器
這一行是一個注釋,聲明了接下來的代碼將定義代理服務器的URL。
const proxyServer = "http-pro.xxx.com:9010"
這里定義了一個常量proxyServer
,它的值是代理服務器的URL,格式為http://host:port
。
// 代理隧道驗證信息
這一行是一個注釋,聲明了接下來的代碼將定義代理隧道的驗證信息。
const proxyUser = "xxxxxxxxx"
這里定義了一個常量proxyUser
,它的值是代理隧道的用戶名。
const proxyPass = "xxxxxxxxx"
這里定義了一個常量proxyPass
,它的值是代理隧道的密碼。
// 初始化代理URL
這一行是一個注釋,說明接下來的代碼將創(chuàng)建代理URL。
proxyUrl, _ := url.Parse("http://" + proxyUser + ":" + proxyPass + "@" + proxyServer)
這行代碼使用url.Parse
函數(shù)創(chuàng)建了一個代理URL。它將代理隧道的用戶名、密碼和代理服務器地址組合成一個URL,格式為http://username:password@host:port
。_
是忽略返回值的約定,因為返回值通常不需要使用。
// 創(chuàng)建請求選項
這一行是一個注釋,說明接下來的代碼將創(chuàng)建一個grequests.RequestOptions
結構體,用于配置HTTP請求。
ro := &grequests.RequestOptions{
這里開始定義grequests.RequestOptions
結構體變量ro
。
Proxies: map[string]*url.URL{
這里定義了Proxies
字段,它是一個映射,將協(xié)議(如"http")映射到代理URL。
"http": proxyUrl,
這行代碼將代理URL設置為HTTP協(xié)議的代理。
},
這是映射定義的結束。
Headers: map[string]string{
這里定義了Headers
字段,它是一個映射,將HTTP頭字段(如"user-agent")映射到相應的值。
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
這行代碼設置了一個HTTP頭字段,即用戶代理(User-Agent),用于標識發(fā)起請求的客戶端。
},
這是映射定義的結束。
}
這是grequests.RequestOptions
結構體變量的定義結束。
// 發(fā)起GET請求
這一行是一個注釋,說明接下來的代碼將發(fā)起一個GET請求。
resp, err := grequests.Get("http://www.example.com", ro)
這行代碼使用grequests.Get
函數(shù)發(fā)起一個GET請求。http://www.example.com
是請求的目標URL,而ro
是請求的配置選項。grequests.Get
函數(shù)會返回一個Response
對象和一個可能的錯誤。
if err != nil {
如果grequests.Get
函數(shù)調(diào)用時發(fā)生錯誤,這個條件塊會執(zhí)行。
fmt.Println("Error:", err)
這行代碼打印出錯誤信息。
return
這行代碼表示如果發(fā)生錯誤,函數(shù)將返回,不繼續(xù)執(zhí)行。
}
這是錯誤處理塊的結束。
fmt.Println("Status code:", resp.StatusCode)
如果請求成功,這行代碼會打印出響應的狀態(tài)碼。
fmt.Println("Response:", resp.String())
4.5 Gorequests 使用session
下面是使用Session的一個例子:
session := grequests.Session{ RequestOptions: &grequests.RequestOptions{ Headers: map[string]string{ "authority": "mp3.haoge500.com", "referer": "https://www.zz123.com/", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36", }, }, }
五、HTTP服務端代碼
package main import ( "encoding/json" "github.com/gin-gonic/gin" "net/http" "os" ) type Book struct { ID string `json:"id"` Name string `json:"name"` } type BookHandler struct { } func (b *BookHandler) RegisterRoutes(server *gin.Engine) { bg := server.Group("/book") bg.POST("/upload", b.Upload) bg.POST("/create", b.Create) bg.GET("/", b.GetAllBooks) // 查詢書籍 } func (b *BookHandler) Upload(ctx *gin.Context) { // 從請求中獲取文件 file, err := ctx.FormFile("file") if err != nil { ctx.JSON(http.StatusBadRequest, gin.H{"error": "無法獲取上傳的文件"}) return } // 將文件保存到服務器 // 注意:這里需要確保保存文件的目錄存在,并且服務器有寫入權限 savePath := "./uploads/" + file.Filename if err := ctx.SaveUploadedFile(file, savePath); err != nil { ctx.JSON(http.StatusInternalServerError, gin.H{"error": "文件保存失敗"}) return } ctx.JSON(http.StatusOK, gin.H{"message": "文件上傳成功"}) } func (b *BookHandler) Create(ctx *gin.Context) { var req Book if err := ctx.Bind(&req); err != nil { return } // 將新的書籍數(shù)據(jù)保存到data.json文件中 if err := addBookToFile(&req); err != nil { ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save book data"}) return } ctx.JSON(http.StatusOK, gin.H{"message": "Book added successfully"}) } func (b *BookHandler) GetAllBooks(c *gin.Context) { // 從data.json文件中讀取書籍數(shù)據(jù) books, err := getBooksFromFile() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read book data"}) return } // 獲取URL查詢參數(shù)中的id id := c.Query("id") // 如果提供了ID,查找具有匹配ID的書籍列表 if id != "" { // 查找具有匹配ID的書籍 var foundBooks []Book for _, book := range books { if book.ID == id { foundBooks = append(foundBooks, book) } } // 如果找到了匹配的書籍,返回這些書籍 if len(foundBooks) > 0 { c.JSON(http.StatusOK, foundBooks) return } // 如果沒有找到匹配的書籍,返回404 c.JSON(http.StatusNotFound, gin.H{"error": "Books not found"}) return } // 如果沒有提供ID,返回所有書籍 c.JSON(http.StatusOK, books) } func addBookToFile(book *Book) error { // 讀取現(xiàn)有的data.json文件內(nèi)容 var books []Book data, err := os.ReadFile("data.json") if err != nil && !os.IsNotExist(err) { return err } // 如果文件存在,解析現(xiàn)有的書籍數(shù)據(jù) if err == nil { if err := json.Unmarshal(data, &books); err != nil { return err } } // 將新的書籍添加到數(shù)組中 books = append(books, *book) // 將更新后的書籍數(shù)組序列化為JSON newData, err := json.MarshalIndent(books, "", " ") if err != nil { return err } // 將序列化的JSON數(shù)據(jù)寫入data.json文件 if err := os.WriteFile("data.json", newData, 0644); err != nil { return err } return nil } func getBooksFromFile() ([]Book, error) { // 讀取data.json文件內(nèi)容 data, err := os.ReadFile("data.json") if err != nil { return nil, err } // 解析JSON數(shù)據(jù)到書籍數(shù)組中 var books []Book if err := json.Unmarshal(data, &books); err != nil { return nil, err } return books, nil } func InitWebServer(bookHandler *BookHandler) *gin.Engine { server := gin.Default() bookHandler.RegisterRoutes(server) return server } func main() { // 確保上傳目錄存在 os.MkdirAll("./uploads", 0755) bookHandler := &BookHandler{} server := InitWebServer(bookHandler) server.Run(":8080") // 在8080端口啟動服務器 }
以上就是Go標準庫之Requests的介紹與基本使用的詳細內(nèi)容,更多關于Go Requests的資料請關注腳本之家其它相關文章!
相關文章
gin通過go build -tags實現(xiàn)json包切換及庫分析
這篇文章主要為大家介紹了gin通過go build -tags實現(xiàn)json包切換及庫分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-09-09