Skip to main content

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

BindShouldBind是通用的方法,能够根据自动处理多种格式的数据,而其他方法则是针对特定格式的数据进行绑定。

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

BindJSONShouldBindJSON将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

BindXMLShouldBindXML将XML请求体绑定到结构体,用于处理Content-Typeapplication/xmltext/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

BindHeaderShouldBindHeader将请求头的值绑定到结构体中。

/**
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

BindUriShouldBindUri将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

BindYAMLShouldBindYAML将YAML请求体绑定到结构体,主要处理Content-Typeapplication/x-yaml的请求。

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)
})