Go標(biāo)準(zhǔn)庫之Requests的介紹與基本使用
一、介紹
官方文檔 DOC: https://pkg.go.dev/github.com/levigross/grequests
Github: http://github.com/levigross/grequests
Python中的Requests庫非常強(qiáng)大,所以Go開發(fā)者模仿Python的Requests庫,由此誕生了Grequests庫。Grequests提供了一系列便利功能,使得發(fā)送HTTP請(qǐng)求變得簡單高效。下面就是Grequests在Golang中實(shí)現(xiàn)的一些關(guān)鍵特性:
- 響應(yīng)序列化:
Grequests支持將HTTP響應(yīng)內(nèi)容序列化為JSON和XML格式,讓處理API響應(yīng)時(shí)更為方便。 - 文件上傳和下載:提供了便捷的方式來上傳和下載文件,無需復(fù)雜的配置。
- HTTP動(dòng)詞支持:支持廣泛的HTTP動(dòng)詞,包括GET、HEAD、POST、PUT、DELETE、PATCH以及OPTIONS,可以覆蓋大多數(shù)HTTP請(qǐng)求場景。
二、安裝
要開始使用Grequests庫,你需要先在你的Go環(huán)境中安裝它。通過下面的命令即可完成安裝:
go get -u github.com/levigross/grequests
三、導(dǎo)入
在安裝完Grequests后,你可以通過import語句把它引入到你的Go代碼中:
import "github.com/levigross/grequests"
四、基本使用
4.1 發(fā)送GET 請(qǐng)求
下面是一個(gè)發(fā)送GET請(qǐng)求的示例,其中演示了如何獲取HTTP響應(yīng)并打印出來:
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("請(qǐng)求超時(shí)!")
}
// 解析響應(yīng)的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請(qǐng)求,然后檢查是否有錯(cuò)誤發(fā)生。如果沒有錯(cuò)誤,就可以通過resp.Json()方法獲取響應(yīng)的文本內(nèi)容。
4.2 POST請(qǐng)求發(fā)送JSON數(shù)據(jù)
在下面的例子中,我們創(chuàng)建了一個(gè)map對(duì)象來保存我們想要發(fā)送的JSON數(shù)據(jù)。然后我們通過ROption創(chuàng)建了一個(gè)請(qǐng)求選項(xiàng)對(duì)象,并在其中指定了JSON為發(fā)送的數(shù)據(jù)類型。最后,我們調(diào)用Post方法來發(fā)送請(qǐng)求:
func Post() {
postData := map[string]string{
"id": "1",
"name": "Go入門到進(jìn)階",
}
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入門到進(jìn)階"}
這里定義了一個(gè)map[string]string類型的變量postData,其中包含了兩個(gè)鍵值對(duì),分別是"id"和"name",它們的值分別是"1"和"Go入門到進(jìn)階"。
geq := &grequests.RequestOptions{JSON: postData}
這里創(chuàng)建了一個(gè)grequests.RequestOptions類型的變量geq。grequests.RequestOptions是一個(gè)結(jié)構(gòu)體,用于配置HTTP請(qǐng)求的各種選項(xiàng),如URL、方法、頭信息、數(shù)據(jù)等。在這個(gè)例子中,我們通過JSON字段將postData作為JSON數(shù)據(jù)傳遞給POST請(qǐng)求。
resp, err := grequests.Post("http://127.0.0.1:8080/book/create", geq)
這里調(diào)用grequests.Post函數(shù)發(fā)起一個(gè)POST請(qǐng)求。http://127.0.0.1:8080/book/create是請(qǐng)求的目標(biāo)URL,而geq是請(qǐng)求的配置選項(xiàng)。grequests.Post函數(shù)會(huì)返回一個(gè)Response對(duì)象和一個(gè)可能的錯(cuò)誤。
if err != nil { log.Fatalln("Unable to make request: ", err) }
如果grequests.Post函數(shù)調(diào)用時(shí)發(fā)生錯(cuò)誤,這個(gè)條件塊會(huì)執(zhí)行。log.Fatalln函數(shù)會(huì)打印錯(cuò)誤消息并退出程序。
fmt.Println(resp.String())
如果請(qǐng)求成功,這個(gè)條件塊會(huì)執(zhí)行。resp.String()方法會(huì)返回響應(yīng)體的字符串表示,然后使用fmt.Println函數(shù)將其打印到標(biāo)準(zhǔn)輸出。
總的來說,這段代碼的作用是向本地服務(wù)器(假設(shè)在127.0.0.1:8080上)的/book/create路徑發(fā)送一個(gè)POST請(qǐng)求,請(qǐng)求體是JSON格式的數(shù)據(jù),包含一個(gè)ID和書名。如果請(qǐng)求成功,它會(huì)打印出服務(wù)器的響應(yīng)。如果請(qǐng)求失敗,它會(huì)打印出錯(cuò)誤信息并退出程序。
4.3 Post 文件上傳
文件上傳同樣簡單。你可以通過RequestOptions指定文件:
func UploadFile() {
// 允許您通過指定磁盤上的位置來創(chuàng)建FileUpload結(jié)構(gòu)片
// 打開要上傳的文件
file, err := os.Open("./go.mod")
if err != nil {
log.Fatalln("Unable to open file: ", err)
}
defer file.Close()
// 創(chuàng)建FileUpload結(jié)構(gòu)片
ro := &grequests.RequestOptions{
Files: []grequests.FileUpload{{
FileName: "1.txt", // 上傳后的文件名稱
FieldName: "file", // 上傳文件對(duì)應(yīng)字段
FileContents: file, // 使用文件內(nèi)容作為FileContents
}},
}
// 發(fā)送POST請(qǐng)求
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)建了一個(gè)FileUpload結(jié)構(gòu),通過FileName、FieldName和FileContents來指定我們要上傳的文件詳情。
4.4 GoRequests 使用代理
gorequest代理,下面是一個(gè)簡單的例子,需要把Proxies中的URL添加為*url.URL代理:
func Proxy() {
// 代理服務(wù)器
const proxyServer = "http-pro.xxx.com:9010"
// 代理隧道驗(yàn)證信息
const proxyUser = "xxxxxxxxx"
const proxyPass = "xxxxxxxxx"
// 初始化代理URL
proxyUrl, _ := url.Parse("http://" + proxyUser + ":" + proxyPass + "@" + proxyServer)
// 創(chuàng)建請(qǐng)求選項(xià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請(qǐng)求
resp, err := grequests.Get("http://www.example.com", ro)
if err != nil {
fmt.Println("Error:", err)
return
}
// 打印響應(yīng)狀態(tài)碼
fmt.Println("Status code:", resp.StatusCode)
// 打印響應(yīng)體
fmt.Println("Response:", resp.String())
}
下面是代碼的逐行解釋:
// 代理服務(wù)器
這一行是一個(gè)注釋,聲明了接下來的代碼將定義代理服務(wù)器的URL。
const proxyServer = "http-pro.xxx.com:9010"
這里定義了一個(gè)常量proxyServer,它的值是代理服務(wù)器的URL,格式為http://host:port。
// 代理隧道驗(yàn)證信息
這一行是一個(gè)注釋,聲明了接下來的代碼將定義代理隧道的驗(yàn)證信息。
const proxyUser = "xxxxxxxxx"
這里定義了一個(gè)常量proxyUser,它的值是代理隧道的用戶名。
const proxyPass = "xxxxxxxxx"
這里定義了一個(gè)常量proxyPass,它的值是代理隧道的密碼。
// 初始化代理URL
這一行是一個(gè)注釋,說明接下來的代碼將創(chuàng)建代理URL。
proxyUrl, _ := url.Parse("http://" + proxyUser + ":" + proxyPass + "@" + proxyServer)
這行代碼使用url.Parse函數(shù)創(chuàng)建了一個(gè)代理URL。它將代理隧道的用戶名、密碼和代理服務(wù)器地址組合成一個(gè)URL,格式為http://username:password@host:port。_是忽略返回值的約定,因?yàn)榉祷刂低ǔ2恍枰褂谩?/p>
// 創(chuàng)建請(qǐng)求選項(xiàng)
這一行是一個(gè)注釋,說明接下來的代碼將創(chuàng)建一個(gè)grequests.RequestOptions結(jié)構(gòu)體,用于配置HTTP請(qǐng)求。
ro := &grequests.RequestOptions{
這里開始定義grequests.RequestOptions結(jié)構(gòu)體變量ro。
Proxies: map[string]*url.URL{
這里定義了Proxies字段,它是一個(gè)映射,將協(xié)議(如"http")映射到代理URL。
"http": proxyUrl,
這行代碼將代理URL設(shè)置為HTTP協(xié)議的代理。
},
這是映射定義的結(jié)束。
Headers: map[string]string{
這里定義了Headers字段,它是一個(gè)映射,將HTTP頭字段(如"user-agent")映射到相應(yīng)的值。
"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",
這行代碼設(shè)置了一個(gè)HTTP頭字段,即用戶代理(User-Agent),用于標(biāo)識(shí)發(fā)起請(qǐng)求的客戶端。
},
這是映射定義的結(jié)束。
}
這是grequests.RequestOptions結(jié)構(gòu)體變量的定義結(jié)束。
// 發(fā)起GET請(qǐng)求
這一行是一個(gè)注釋,說明接下來的代碼將發(fā)起一個(gè)GET請(qǐng)求。
resp, err := grequests.Get("http://www.example.com", ro)
這行代碼使用grequests.Get函數(shù)發(fā)起一個(gè)GET請(qǐng)求。http://www.example.com是請(qǐng)求的目標(biāo)URL,而ro是請(qǐng)求的配置選項(xiàng)。grequests.Get函數(shù)會(huì)返回一個(gè)Response對(duì)象和一個(gè)可能的錯(cuò)誤。
if err != nil {
如果grequests.Get函數(shù)調(diào)用時(shí)發(fā)生錯(cuò)誤,這個(gè)條件塊會(huì)執(zhí)行。
fmt.Println("Error:", err)
這行代碼打印出錯(cuò)誤信息。
return
這行代碼表示如果發(fā)生錯(cuò)誤,函數(shù)將返回,不繼續(xù)執(zhí)行。
}
這是錯(cuò)誤處理塊的結(jié)束。
fmt.Println("Status code:", resp.StatusCode)
如果請(qǐng)求成功,這行代碼會(huì)打印出響應(yīng)的狀態(tài)碼。
fmt.Println("Response:", resp.String())
4.5 Gorequests 使用session
下面是使用Session的一個(gè)例子:
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服務(wù)端代碼
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) {
// 從請(qǐng)求中獲取文件
file, err := ctx.FormFile("file")
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "無法獲取上傳的文件"})
return
}
// 將文件保存到服務(wù)器
// 注意:這里需要確保保存文件的目錄存在,并且服務(wù)器有寫入權(quán)限
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
}
// 將新的書籍?dāng)?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文件中讀取書籍?dāng)?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)有的書籍?dāng)?shù)據(jù)
if err == nil {
if err := json.Unmarshal(data, &books); err != nil {
return err
}
}
// 將新的書籍添加到數(shù)組中
books = append(books, *book)
// 將更新后的書籍?dāng)?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ù)到書籍?dāng)?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端口啟動(dòng)服務(wù)器
}
以上就是Go標(biāo)準(zhǔn)庫之Requests的介紹與基本使用的詳細(xì)內(nèi)容,更多關(guān)于Go Requests的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Gin+Gorm實(shí)現(xiàn)CRUD的實(shí)戰(zhàn)
本文主要介紹了Gin+Gorm實(shí)現(xiàn)CRUD的實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02
Go實(shí)現(xiàn)數(shù)據(jù)脫敏的方案設(shè)計(jì)
在一些常見的業(yè)務(wù)場景中可能涉及到用戶的手機(jī)號(hào),銀行卡號(hào)等敏感數(shù)據(jù),對(duì)于這部分的數(shù)據(jù)經(jīng)常需要進(jìn)行數(shù)據(jù)脫敏處理,就是將此部分?jǐn)?shù)據(jù)隱私化,防止數(shù)據(jù)泄露,所以本文給大家介紹了Go實(shí)現(xiàn)數(shù)據(jù)脫敏的方案設(shè)計(jì),需要的朋友可以參考下2024-05-05
Golang設(shè)計(jì)模式之單例模式詳細(xì)講解
單例模式很容易記住。就像名稱一樣,它只能提供對(duì)象的單一實(shí)例,保證一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問該實(shí)例的方法。本文就來聊聊Go語言中的單例模式,感興趣的小伙伴可以了解一下2023-01-01
Go遍歷struct,map,slice的實(shí)現(xiàn)
本文主要介紹了Go語言遍歷結(jié)構(gòu)體、切片和字典的方法,對(duì)大家的學(xué)習(xí)具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06
GoLang之標(biāo)準(zhǔn)庫encoding/json包
本文主要介紹了GoLang之標(biāo)準(zhǔn)庫encoding/json包,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
gin通過go build -tags實(shí)現(xiàn)json包切換及庫分析
這篇文章主要為大家介紹了gin通過go build -tags實(shí)現(xiàn)json包切換及庫分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09

