官方文档地址(中文):https://gin-gonic.com/zh-cn/docs/
注:没用过Gin的读者强烈建议先阅读第一节:Gin操作指南:开山篇。
本节演示GET绑定,包括绑定表单数据至自定义结构体,绑定查询字符串或表单数据,只绑定url查询字符串,查询字符串参数,设置和获取Cookie 从reader读取数据。在开始之前,我们需要在”02请求参数处理“目录下打开命令行,执行如下命令来创建子目录:
mkdir 绑定表单数据至自定义结构体 绑定查询字符串或表单数据 只绑定url查询字符串 查询字符串参数 设置和获取Cookie 从reader读取数据
然后下载安装postman,注册登录后,点击新建,如图
目录
- 一、绑定表单数据至自定义结构体
- 二、绑定查询字符串或表单数据
- 三、只绑定url查询字符串
- 四、查询字符串参数
- 五、从reader读取数据
- 六、设置和获取Cookie
一、绑定表单数据至自定义结构体
package mainimport ("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 请求 /getbr.GET("/getc", GetDataC) // 处理 GET 请求 /getcr.GET("/getd", GetDataD) // 处理 GET 请求 /getdr.Run() // 启动服务器,监听默认端口 8080
}
效果
二、绑定查询字符串或表单数据
package mainimport ("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) // 打印绑定的 Namelog.Println(person.Address) // 打印绑定的 Address}// 尝试从 JSON 请求体中绑定数据if c.BindJSON(&person) == nil { // 使用 BindJSON 方法,专门用于绑定 JSON 数据log.Println("====== Bind By JSON ======") // 绑定成功后,打印日志log.Println(person.Name) // 打印绑定的 Namelog.Println(person.Address) // 打印绑定的 Address}// 返回响应给客户端,状态码 200,内容为 "Success"c.String(200, "Success")
}
通过查询字符串测试:
通过 Postman 发送 JSON 数据测试:
使用 Postman 创建一个新的请求,方法选择 GET,URL 为 http://localhost:8085/testing。
在 Body 选项卡中按下图设置,点击send即可看到效果:
三、只绑定url查询字符串
package mainimport ("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)// 监听并启动服务,监听的端口为 8085route.Run(":8085")
}// 处理请求的处理器函数
func startPage(c *gin.Context) {var person Person // 创建一个 Person 结构体实例,用于接收请求中的数据// 通过 BindQuery 绑定查询字符串参数,即从 URL 中的查询参数绑定 name 和 address// 例如:/testing?name=John&address=NewYorkif c.BindQuery(&person) == nil { // 如果绑定没有出错,返回 nil// 绑定成功后打印日志,输出绑定的 name 和 addresslog.Println("====== Only Bind Query String ======") // 输出绑定信息的提示日志log.Println(person.Name) // 输出绑定的 Name 值log.Println(person.Address) // 输出绑定的 Address 值}// 返回 HTTP 状态码 200,和字符串 "Success" 作为响应内容c.String(200, "Success")
}
效果
四、查询字符串参数
package mainimport ("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=Doerouter.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" 作为 firstnamec.String(http.StatusOK, "Hello %s %s", firstname, lastname)})// 运行 Gin 服务器,监听在本地的 8080 端口上router.Run(":8080")
}
效果
五、从reader读取数据
package mainimport ("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-LengthcontentLength := 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
package mainimport ("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" 的 Cookiecookie, 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 服务器,监听在默认端口 8080router.Run()
}
打开浏览器,访问http://localhost:8080/cookie
首次访问时,会在控制台看到输出 Cookie value: NotSet
,按F12-网络,刷新页面,会看到有个名称为cookie的缓存,同时控制台的输出变为了Cookie value: test
,如图