Bind
Bind
在Gin框架中,Bind系列方法用于将请求中的数据绑定到Go语言的结构体中。Gin提供了多种Bind方法来处理不同类型的请求数据,比如JSON、XML、表单、Query参数等。这些方法的作用是简化请求参数的解析和验证。
Bind可分为两类:Must Bind和Should Bind,这两类方法的主要区别在于它们如何处理绑定错误。
Must Bind
这类方法在发生绑定错误时,会自动返回400 Bad Request响应,并终止请求的进一步处理,适用于希望在出现错误时立即响应客户端错误,并且不需要手动处理错误的情况。
此类方法包括:
Bind。BindJSON。BindXML。BindQuery。BindYAML。BindHeader。BindUri。
Should Bind
这类方法在发生绑定错误时,不会自动返回400 Bad Request响应,而是将错误返回给调用者,由调用者决定如何处理错误,适用于需要在绑定失败时进行自定义错误处理的场景。
此类方法包括:
ShouldBind。ShouldBindJSON。ShouldBindXML。ShouldBindQuery。ShouldBindYAML、。ShouldBindHeader。ShouldBindUri。
Bind
Bind和ShouldBind是通用的方法,能够根据自动处理多种格式的数据,而其他方法则是针对特定格式的数据进行绑定。
Must Bind和Should Bind的底层都是调用ShouldBindWith方法实现绑定,而Must Bind只是在绑定失败的时候自动抛出400错误。
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
type Info struct {
Name string `json:"name" xml:"name" uri:"name"`
Age uint8 `json:"age" xml:"age" uri:"name"`
IsMarriage bool `json:"isMarriage" xml:"is-marriage" uri:"isMarriage"`
}
func main() {
r := gin.Default()
r.POST("/info", func(ctx *gin.Context) {
var info Info
err := ctx.Bind(&info)
// err := ctx.ShouldBind(&info)
if err != nil {
fmt.Println(err.Error())
panic(err.Error())
}
ctx.JSON(http.StatusOK, info)
})
r.Run()
}
BindJSON
BindJSON和ShouldBindJSON将JSON请求体绑定到结构体,如果请求的Content-Type不是application/json或者JSON解析失败,它会返回错误,BindJSON会自动响应400 Bad Request。
/**
Request:
{
"name": "Tom",
"age": 12,
"isMarriage": false
}
*/
r.POST("/info", func(ctx *gin.Context) {
var info Info
err := ctx.BindJSON(&info)
// err := ctx.ShouldBindJSON(&info)
if err != nil {
fmt.Println(err.Error())
panic(err.Error())
}
ctx.JSON(http.StatusOK, info)
})
BindXML
BindXML和ShouldBindXML将XML请求体绑定到结构体,用于处理Content-Type为application/xml或text/xml的请求。
/**
Request:
<info>
<name>Tom</name>
<age>12</age>
<is-marriage>false</is-marriage>
</info>
*/
r.POST("/info", func(ctx *gin.Context) {
var info Info
err := ctx.BindXML(&info)
// err := ctx.ShouldBindXML(&info)
if err != nil {
fmt.Println(err.Error())
panic(err.Error())
}
ctx.JSON(http.StatusOK, info)
})
BindQuery
BindQuery和ShouldBindQuery`将URL的查询参数绑定到结构体中。
/**
Request:
/info?Name=tom&Age=12&IsMarriage=false
*/
r.GET("/info", func(ctx *gin.Context) {
var info Info
err := ctx.BindXML(&info)
// err := ctx.ShouldBindXML(&info)
if err != nil {
fmt.Println(err.Error())
panic(err.Error())
}
ctx.JSON(http.StatusOK, info)
})
BindHeader
BindHeader和ShouldBindHeader将请求头的值绑定到结构体中。
/**
Request Header:
token: 123
*/
type InfoHeader struct {
Token string `header:"token" json:"token"`
}
r.GET("/info", func(ctx *gin.Context) {
var info InfoHeader
err := ctx.BindHeader(&info)
// err := ctx.ShouldBindHeader(&info)
if err != nil {
fmt.Println(err.Error())
panic(err.Error())
}
ctx.JSON(http.StatusOK, info)
})
BindUri
BindUri和ShouldBindUri将URL路径参数绑定到结构体,适用于在路由路径中包含动态参数的场景,比如/user/:id这种形式。
/*
Request:
/info/1
*/
r.GET("/info/:id", func(ctx *gin.Context) {
var info Info
err := ctx.BindUri(&info)
// err := ctx.ShouldBindUri(&info)
if err != nil {
fmt.Println(err.Error())
panic(err.Error())
}
ctx.JSON(http.StatusOK, info)
})
BindYAML
BindYAML和ShouldBindYAML将YAML请求体绑定到结构体,主要处理Content-Type为application/x-yaml的请求。
- main.go
- index.html
r.POST("/info", func(ctx *gin.Context) {
var info Info
err := ctx.BindYAML(&info)
// err := ctx.ShouldBindYAML(&info)
if err != nil {
fmt.Println(err.Error())
panic(err.Error())
}
ctx.JSON(http.StatusOK, info)
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/js-yaml/4.1.0/js-yaml.js"></script>
</head>
<body>
<script>
$.ajax({
url: "http://localhost:8080/info",
method: "post",
contentType: "application/x-yaml",
data: jsyaml.dump({
"name": "tom",
"age": 12,
"isMarriage": false
})
}).then((res) => {
// {name: 'tom', age: 12, isMarriage: false}
console.log(res);
})
</script>
</body>
</html>