Gin框架操作指南04:GET绑定

官方文档地址(中文):https://gin-gonic.com/zh-cn/docs/

注:本教程采用工作区机制,所以一个项目下载了Gin框架,其余项目就无需重复下载,想了解的读者可阅读第一节:Gin操作指南:开山篇

本节演示GET绑定,包括绑定表单数据至自定义结构体,绑定查询字符串或表单数据,只绑定url查询字符串,查询字符串参数,设置和获取Cookie 从reader读取数据。在开始之前,我们需要在"02请求参数处理"目录下打开命令行,执行如下命令来创建子目录:

bash 复制代码
mkdir 绑定表单数据至自定义结构体 绑定查询字符串或表单数据 只绑定url查询字符串 查询字符串参数 设置和获取Cookie 从reader读取数据

然后下载安装postman,注册登录后,点击新建,如图

目录

一、绑定表单数据至自定义结构体

go 复制代码
package main

import (
	"github.com/gin-gonic/gin" // 引入 gin-gonic/gin 包,用于构建 HTTP 服务
)

// StructA 定义一个结构体,包含一个字段 FieldA,绑定表单字段 field_a
type StructA struct {
	FieldA string `form:"field_a"` // 绑定来自表单数据的 field_a
}

// StructB 定义一个包含嵌套结构体和其他字段的结构体
type StructB struct {
	NestedStruct StructA // 嵌套的 StructA 结构体
	FieldB       string  `form:"field_b"` // 绑定来自表单数据的 field_b
}

// StructC 定义一个包含指向嵌套结构体的指针和其他字段的结构体
type StructC struct {
	NestedStructPointer *StructA // 指向嵌套的 StructA 结构体的指针
	FieldC              string   `form:"field_c"` // 绑定来自表单数据的 field_c
}

// StructD 定义一个包含嵌套匿名结构体和其他字段的结构体
type StructD struct {
	NestedAnonyStruct struct {
		FieldX string `form:"field_x"` // 绑定来自表单数据的 field_x
	} // 嵌套的匿名结构体
	FieldD string `form:"field_d"` // 绑定来自表单数据的 field_d
}

// GetDataB 处理 GET 请求,将表单数据绑定至 StructB,并返回 JSON 响应
func GetDataB(c *gin.Context) {
	var b StructB // 创建 StructB 的实例
	c.Bind(&b)    // 将请求中的表单数据绑定到结构体 b

	// 返回 JSON 响应,包含结构体 b 的字段
	c.JSON(200, gin.H{
		"a": b.NestedStruct, // 返回 NestedStruct
		"b": b.FieldB,       // 返回 FieldB
	})
}

// GetDataC 处理 GET 请求,将表单数据绑定至 StructC,并返回 JSON 响应
func GetDataC(c *gin.Context) {
	var b StructC // 创建 StructC 的实例
	c.Bind(&b)    // 将请求中的表单数据绑定到结构体 b

	// 返回 JSON 响应,包含结构体 b 的字段
	c.JSON(200, gin.H{
		"a": b.NestedStructPointer, // 返回 NestedStructPointer
		"c": b.FieldC,              // 返回 FieldC
	})
}

// GetDataD 处理 GET 请求,将表单数据绑定至 StructD,并返回 JSON 响应
func GetDataD(c *gin.Context) {
	var b StructD // 创建 StructD 的实例
	c.Bind(&b)    // 将请求中的表单数据绑定到结构体 b

	// 返回 JSON 响应,包含结构体 b 的字段
	c.JSON(200, gin.H{
		"x": b.NestedAnonyStruct, // 返回 NestedAnonyStruct
		"d": b.FieldD,            // 返回 FieldD
	})
}

// main 函数设置路由并启动服务器
func main() {
	r := gin.Default() // 创建默认的 Gin 路由引擎

	// 设置路由,绑定处理函数
	r.GET("/getb", GetDataB) // 处理 GET 请求 /getb
	r.GET("/getc", GetDataC) // 处理 GET 请求 /getc
	r.GET("/getd", GetDataD) // 处理 GET 请求 /getd

	r.Run() // 启动服务器,监听默认端口 8080
}

效果

二、绑定查询字符串或表单数据

go 复制代码
package main

import (
	"log" // 引入 log 包,用于日志输出

	"github.com/gin-gonic/gin" // 引入 gin-gonic/gin 包,用于构建 HTTP 服务
)

// 定义一个结构体 Person,用于绑定请求中的数据
type Person struct {
	Name    string `form:"name" json:"name"`       // `form:"name"` 用于表单提交,`json:"name"` 用于 JSON 请求
	Address string `form:"address" json:"address"` // `form:"address"` 用于表单提交,`json:"address"` 用于 JSON 请求
}

func main() {
	route := gin.Default() // 创建一个 gin 路由实例,带有默认的日志和恢复中间件

	// 处理 GET 请求的路由,访问 /testing 路由时,调用 startPage 函数处理请求
	route.GET("/testing", startPage)

	// 运行服务器,监听 8085 端口
	route.Run(":8085")
}

// 处理请求的函数,绑定并处理表单和 JSON 数据
func startPage(c *gin.Context) {
	var person Person // 定义 Person 结构体变量,用于接收绑定的数据

	// 尝试从查询字符串中绑定数据 (name 和 address)
	if c.Bind(&person) == nil { // c.Bind 自动根据请求的 Content-Type 选择合适的绑定方法
		log.Println("====== Bind By Query String ======") // 绑定成功后,打印日志
		log.Println(person.Name)                          // 打印绑定的 Name
		log.Println(person.Address)                       // 打印绑定的 Address
	}

	// 尝试从 JSON 请求体中绑定数据
	if c.BindJSON(&person) == nil { // 使用 BindJSON 方法,专门用于绑定 JSON 数据
		log.Println("====== Bind By JSON ======") // 绑定成功后,打印日志
		log.Println(person.Name)                  // 打印绑定的 Name
		log.Println(person.Address)               // 打印绑定的 Address
	}

	// 返回响应给客户端,状态码 200,内容为 "Success"
	c.String(200, "Success")
}

通过查询字符串测试

通过 Postman 发送 JSON 数据测试

使用 Postman 创建一个新的请求,方法选择 GET,URL 为 http://localhost:8085/testing。

在 Body 选项卡中按下图设置,点击send即可看到效果:

三、只绑定url查询字符串

go 复制代码
package main

import (
	"log" // 引入 log 包,用于日志输出

	"github.com/gin-gonic/gin" // 引入 gin-gonic/gin 包,用于创建 HTTP web 框架
)

// 定义一个 Person 结构体,用于接收查询参数中的 name 和 address
type Person struct {
	Name    string `form:"name"`    // form:"name" 指定该字段从查询参数 name 中提取
	Address string `form:"address"` // form:"address" 指定该字段从查询参数 address 中提取
}

func main() {
	route := gin.Default() // 创建一个 Gin 实例,带有默认的日志和恢复中间件

	// route.Any 注册一个处理所有 HTTP 方法(GET、POST、PUT 等)到 /testing 路由的处理器函数
	route.Any("/testing", startPage)

	// 监听并启动服务,监听的端口为 8085
	route.Run(":8085")
}

// 处理请求的处理器函数
func startPage(c *gin.Context) {
	var person Person // 创建一个 Person 结构体实例,用于接收请求中的数据

	// 通过 BindQuery 绑定查询字符串参数,即从 URL 中的查询参数绑定 name 和 address
	// 例如:/testing?name=John&address=NewYork
	if c.BindQuery(&person) == nil { // 如果绑定没有出错,返回 nil
		// 绑定成功后打印日志,输出绑定的 name 和 address
		log.Println("====== Only Bind Query String ======") // 输出绑定信息的提示日志
		log.Println(person.Name)                            // 输出绑定的 Name 值
		log.Println(person.Address)                         // 输出绑定的 Address 值
	}

	// 返回 HTTP 状态码 200,和字符串 "Success" 作为响应内容
	c.String(200, "Success")
}

效果

四、查询字符串参数

go 复制代码
package main

import (
	"net/http"          // 导入 HTTP 包,用于处理 HTTP 状态码等
	"github.com/gin-gonic/gin" // 导入 Gin 框架包,用于创建 HTTP Web 服务器
)

func main() {
	// 使用 gin.Default() 创建一个默认的 Gin 路由器实例
	// 默认情况下,包含了日志和恢复中间件(用于记录请求日志和处理服务器崩溃时的恢复)
	router := gin.Default()

	// 定义一个 GET 请求的路由处理函数,用于处理 "/welcome" 路由
	// 这个路由会接收 URL 查询参数(Query Parameters),并返回个性化的响应
	// 示例 URL:/welcome?firstname=Jane&lastname=Doe
	router.GET("/welcome", func(c *gin.Context) {
		// 使用 c.DefaultQuery 方法解析 URL 中的 "firstname" 查询参数
		// 如果查询参数不存在,则返回默认值 "Guest"
		firstname := c.DefaultQuery("firstname", "Guest")
		
		// 使用 c.Query 方法获取 URL 中的 "lastname" 查询参数
		// c.Query 是 c.Request.URL.Query().Get("lastname") 的简化版本
		lastname := c.Query("lastname")

		// 使用 c.String 返回一个字符串作为响应
		// 其中包含 HTTP 状态码 http.StatusOK(即 200),并将解析出的 "firstname" 和 "lastname" 插入到响应消息中
		// 如果查询参数没有提供,默认会使用 "Guest" 作为 firstname
		c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
	})

	// 运行 Gin 服务器,监听在本地的 8080 端口上
	router.Run(":8080")
}

效果

五、从reader读取数据

go 复制代码
package main

import (
	"net/http" // 导入 HTTP 包,用于处理 HTTP 请求和响应

	"github.com/gin-gonic/gin" // 导入 Gin 框架包,用于创建 HTTP Web 服务器
)

func main() {
	// 使用 gin.Default() 创建一个默认的 Gin 路由器实例
	router := gin.Default()

	// 定义一个 GET 请求的路由处理函数,用于处理 "/someDataFromReader" 路由
	// 这个路由会从远程 URL 获取数据,并通过 Gin 将该数据发送给客户端
	router.GET("/someDataFromReader", func(c *gin.Context) {
		// 使用 http.Get 方法发起 HTTP GET 请求,尝试从远程服务器获取图像文件
		response, err := http.Get("https://img2.baidu.com/it/u=3545291696,228271590&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1186")

		// 检查是否发生错误,或者返回的 HTTP 状态码是否不是 200 OK
		// 如果发生错误或者状态码不是 200,则返回 HTTP 503 服务不可用状态
		if err != nil || response.StatusCode != http.StatusOK {
			c.Status(http.StatusServiceUnavailable)
			return
		}

		// 获取响应的 Body(即图像文件的二进制数据)
		reader := response.Body

		// 获取文件的内容长度,用于设置响应头中的 Content-Length
		contentLength := response.ContentLength

		// 获取响应头中的 Content-Type,通常是文件的 MIME 类型(如 "image/png")
		contentType := response.Header.Get("Content-Type")

		// 定义额外的 HTTP 响应头,比如 "Content-Disposition" 设置为附件下载,并指定文件名为 "gopher.png"
		extraHeaders := map[string]string{
			"Content-Disposition": `attachment; filename="gopher.png"`, // 提示浏览器以下载的形式处理响应内容
		}

		// 使用 c.DataFromReader 向客户端发送数据
		// 参数包括 HTTP 状态码 200 OK,文件的长度,文件的类型,数据流(即 reader),以及额外的 HTTP 响应头
		c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders)
	})

	// 启动 Gin 服务器,监听在本地的 8080 端口
	router.Run(":8080")
}

注意 :官方文档给的url有问题,手动可以访问,但程序访问不了,这里随便在百度上找了一张图片的url。

效果:

六、设置和获取Cookie

go 复制代码
package main

import (
	"fmt" // 导入 fmt 包,用于格式化输出

	"github.com/gin-gonic/gin" // 导入 Gin 框架
)

func main() {
	// 创建一个默认的 Gin 路由
	router := gin.Default()

	// 定义 GET 请求的路由,当请求路径为 "/cookie" 时执行对应的处理函数
	router.GET("/cookie", func(c *gin.Context) {
		// 尝试获取名为 "gin_cookie" 的 Cookie
		cookie, err := c.Cookie("gin_cookie")

		// 如果没有找到 Cookie 或者发生错误
		if err != nil {
			// 设置默认值
			cookie = "NotSet"
			// 设置一个名为 "gin_cookie" 的 Cookie,有效期为 3600 秒
			c.SetCookie("gin_cookie", "test", 3600, "/", "localhost", false, true)
		}

		// 打印 Cookie 的值
		fmt.Printf("Cookie value: %s \n", cookie)
	})

	// 启动 HTTP 服务器,监听在默认端口 8080
	router.Run()
}

打开浏览器,访问http://localhost:8080/cookie

首次访问时,会在控制台看到输出 Cookie value: NotSet,按F12-网络,刷新页面,会看到有个名称为cookie的缓存,同时控制台的输出变为了Cookie value: test,如图

相关推荐
hkNaruto14 小时前
【P2P】【Go】采用go语言实现udp hole punching 打洞 传输速度测试 ping测试
golang·udp·p2p
入 梦皆星河14 小时前
go中常用的处理json的库
golang
桃园码工17 小时前
2-Gin 框架中的路由 --[Gin 框架入门精讲与实战案例]
gin·路由·实战案例
海绵波波10717 小时前
Gin-vue-admin(2):项目初始化
vue.js·golang·gin
海绵波波10717 小时前
Gin-vue-admin(4):项目创建前端一级页面和二级页面
前端·vue.js·gin
每天写点bug17 小时前
【go每日一题】:并发任务调度器
开发语言·后端·golang
一个不秃头的 程序员17 小时前
代码加入SFTP Go ---(小白篇5)
开发语言·后端·golang
基哥的奋斗历程17 小时前
初识Go语言
开发语言·后端·golang
ZVAyIVqt0UFji1 天前
go-zero负载均衡实现原理
运维·开发语言·后端·golang·负载均衡
唐墨1231 天前
golang自定义MarshalJSON、UnmarshalJSON 原理和技巧
开发语言·后端·golang