一、介绍
官方文档 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 []map[string]interface{} 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 := 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}
这里创建了一个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[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", }, } // 发起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[string]*url.url{
这里定义了proxies
字段,它是一个映射,将协议(如"http")映射到代理url。
"http": proxyurl,
这行代码将代理url设置为http协议的代理。
},
这是映射定义的结束。
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),用于标识发起请求的客户端。
},
这是映射定义的结束。
}
这是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: 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 } // 将新的书籍数据保存到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端口启动服务器 }
以上就是go标准库之requests的介绍与基本使用的详细内容,更多关于go requests的资料请关注代码网其它相关文章!
发表评论