道家人 发表于 2024-5-17 10:25:36

Go 标准库之 GoRequests 介绍与基本使用

目录

[*]一、介绍
[*]二、安装
[*]三、导入
[*]四、基本使用

[*]4.1 发送GET 请求
[*]4.2 POST请求发送JSON数据
[*]4.3 Post 文件上传
[*]4.4 GoRequests 使用署理
[*]4.5 Gorequests 使用session

[*]五、HTTP服务端代码

一、介绍

官方文档 DOC: https://pkg.go.dev/github.com/levigross/grequests
Github: http://github.com/levigross/grequests
Python中的Requests库非常强大,所以Go开发者模仿Python的Requests库,由此诞生了Grequests库。Grequests提供了一系列便利功能,使得发送HTTP请求变得简朴高效。下面就是Grequests在Golang中实现的一些关键特性:

[*]响应序列化:Grequests支持将HTTP响应内容序列化为JSON和XML格式,让处理API响应时更为方便。
[*]文件上传和下载:提供了便捷的方式来上传和下载文件,无需复杂的设置。
[*]HTTP动词支持:支持广泛的HTTP动词,包括GET、HEAD、POST、PUT、DELETE、PATCH以及OPTIONS,可以覆盖大多数HTTP请求场景。
二、安装

要开始使用Grequests库,你需要先在你的Go情况中安装它。通过下面的下令即可完成安装:
go get -u github.com/levigross/grequests三、导入

在安装完Grequests后,你可以通过import语句把它引入到你的Go代码中:
import "github.com/levigross/grequests"四、基本使用

4.1 发送GET 请求

下面是一个发送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数据
        var data []mapinterface{}
        if err := resp.JSON(&data); err != nil {
                log.Fatalln("Unable to parse JSON response: ", err)
        }
        fmt.Println(data)
}上面的代码首先使用Get方法发送GET请求,然后查抄是否有错误发生。如果没有错误,就可以通过resp.Json()方法获取响应的文本内容。
4.2 POST请求发送JSON数据

在下面的例子中,我们创建了一个map对象来保存我们想要发送的JSON数据。然后我们通过ROption创建了一个请求选项对象,并在此中指定了JSON为发送的数据类型。最后,我们调用Post方法来发送请求:
func Post() {
        postData := mapstring{
                "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 := mapstring{"id": "1", "name": "Go入门到进阶"}

[*]这里定义了一个mapstring类型的变量postData,此中包含了两个键值对,分别是"id"和"name",它们的值分别是"1"和"Go入门到进阶"。

[*]geq := &grequests.RequestOptions{JSON: postData}

[*]这里创建了一个grequests.RequestOptions类型的变量geq。grequests.RequestOptions是一个布局体,用于设置HTTP请求的各种选项,如URL、方法、头信息、数据等。在这个例子中,我们通过JSON字段将postData作为JSON数据传递给POST请求。

[*]resp, err := grequests.Post("http://127.0.0.1:8080/book/create", geq)

[*]这里调用grequests.Post函数发起一个POST请求。http://127.0.0.1:8080/book/create是请求的目的URL,而geq是请求的设置选项。grequests.Post函数会返回一个Response对象和一个大概的错误。

[*]if err != nil { log.Fatalln("Unable to make request: ", err) }

[*]如果grequests.Post函数调用时发生错误,这个条件块会实行。log.Fatalln函数会打印错误消息并退出步伐。

[*]fmt.Println(resp.String())

[*]如果请求成功,这个条件块会实行。resp.String()方法会返回响应体的字符串表示,然后使用fmt.Println函数将其打印到标准输出。
总的来说,这段代码的作用是向本地服务器(假设在127.0.0.1:8080上)的/book/create路径发送一个POST请求,请求体是JSON格式的数据,包含一个ID和书名。如果请求成功,它会打印出服务器的响应。如果请求失败,它会打印出错误信息并退出步伐。

4.3 Post 文件上传

文件上传同样简朴。你可以通过RequestOptions指定文件:
func UploadFile() {
        // 允许您通过指定磁盘上的位置来创建FileUpload结构片
        // 打开要上传的文件
        file, err := os.Open("./go.mod")
        if err != nil {
                log.Fatalln("Unable to open file: ", err)
        }
        defer file.Close()

        // 创建FileUpload结构片
        ro := &grequests.RequestOptions{
                Files: []grequests.FileUpload{{
                        FileName:   "1.txt", // 上传后的文件名称
                        FieldName:    "file",// 上传文件对应字段
                        FileContents: file, // 使用文件内容作为FileContents
                }},
        }
        // 发送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())
}在上述代码中,我们创建了一个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)

        // 创建请求选项
        ro := &grequests.RequestOptions{
                Proxies: map*url.URL{
                        "http": proxyUrl,
                },
                Headers: mapstring{
                        "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",
                },
        }

        // 发起GET请求
        resp, err := grequests.Get("http://www.example.com", ro)
        if err != nil {
                fmt.Println("Error:", err)
                return
        }

        // 打印响应状态码
        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

[*]这一行是一个注释,说明接下来的代码将创建署理URL。

[*]proxyUrl, _ := url.Parse("http://" + proxyUser + ":" + proxyPass + "@" + proxyServer)

[*]这行代码使用url.Parse函数创建了一个署理URL。它将署理隧道的用户名、暗码和署理服务器地址组合成一个URL,格式为http://username:password@host:port。_是忽略返回值的约定,由于返回值通常不需要使用。

[*]// 创建请求选项

[*]这一行是一个注释,说明接下来的代码将创建一个grequests.RequestOptions布局体,用于设置HTTP请求。

[*]ro := &grequests.RequestOptions{

[*]这里开始定义grequests.RequestOptions布局体变量ro。

[*]Proxies: map*url.URL{

[*]这里定义了Proxies字段,它是一个映射,将协议(如"http")映射到署理URL。

[*]"http": proxyUrl,

[*]这行代码将署理URL设置为HTTP协议的署理。

[*]},

[*]这是映射定义的结束。

[*]Headers: mapstring{

[*]这里定义了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),用于标识发起请求的客户端。

[*]},

[*]这是映射定义的结束。

[*]}

[*]这是grequests.RequestOptions布局体变量的定义结束。

[*]// 发起GET请求

[*]这一行是一个注释,说明接下来的代码将发起一个GET请求。

[*]resp, err := grequests.Get("http://www.example.com", ro)

[*]这行代码使用grequests.Get函数发起一个GET请求。http://www.example.com是请求的目的URL,而ro是请求的设置选项。grequests.Get函数会返回一个Response对象和一个大概的错误。

[*]if err != nil {

[*]如果grequests.Get函数调用时发生错误,这个条件块会实行。

[*]fmt.Println("Error:", err)

[*]这行代码打印出错误信息。

[*]return

[*]这行代码表示如果发生错误,函数将返回,不继续实行。

[*]}

[*]这是错误处理块的结束。

[*]fmt.Println("Status code:", resp.StatusCode)

[*]如果请求成功,这行代码会打印出响应的状态码。

[*]fmt.Println("Response:", resp.String())
4.5 Gorequests 使用session

下面是使用Session的一个例子:
session := grequests.Session{
                RequestOptions: &grequests.RequestOptions{
                        Headers: mapstring{
                                "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
        }

        // 将新的书籍数据保存到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文件中读取书籍数据
        books, err := getBooksFromFile()
        if err != nil {
                c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read book data"})
                return
        }

        // 获取URL查询参数中的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 {
        // 读取现有的data.json文件内容
        var books []Book
        data, err := os.ReadFile("data.json")
        if err != nil && !os.IsNotExist(err) {
                return err
        }

        // 如果文件存在,解析现有的书籍数据
        if err == nil {
                if err := json.Unmarshal(data, &books); err != nil {
                        return err
                }
        }

        // 将新的书籍添加到数组中
        books = append(books, *book)

        // 将更新后的书籍数组序列化为JSON
        newData, err := json.MarshalIndent(books, "", "    ")
        if err != nil {
                return err
        }

        // 将序列化的JSON数据写入data.json文件
        if err := os.WriteFile("data.json", newData, 0644); err != nil {
                return err
        }

        return nil
}
func getBooksFromFile() ([]Book, error) {
        // 读取data.json文件内容
        data, err := os.ReadFile("data.json")
        if err != nil {
                return nil, err
        }

        // 解析JSON数据到书籍数组中
        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端口启动服务器
}
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Go 标准库之 GoRequests 介绍与基本使用