基础解释
解释: 例如后端获取调用方参数,通常会使用一个结构体,或一个变量来接收,调用方传递的数据会自动映射到该变量上,而不是通过request去手动获取,怎么映射 目前Gin⽀持JSON、XML、YAML和标准表单值的绑定。就是根据Body数据类型,将数据赋值到指定的结构体变量中 (类似于序列化和反序列化) go提供了两套绑定方案
Must bind(可以简单理解为当获取参数映射时如果出现错误会panic),** MustBindWith 支持如下方式:** Bind , BindJSON , BindXML , BindQuery , BindYAML,注意点: 如果存在绑定错误,则终⽌请求,使⽤ c.AbortWithError (400) .SetType (ErrorTypeBind) 即可。将响应状态代码设置为400,Content-Type header设置为 text/plain;charset = utf - 8 。如果在此之后设置响应代码,将会受到警告: [GIN-debug[WARNING] Headers were alreadywritten. Wanted to override status code 400 with 422 将导致已经编写了警告[GIN-debug][warning]标头。如果想更好地控制⾏为,可以考虑使⽤ShouldBind等效⽅法 Should bind(可以简单理解为如果出现错误,会将错误返回由开发人员自己处理),ShouldBindWith 支持如下方式: ShouldBind , ShouldBindJSON , ShouldBindXML , ShouldBindQuery , ShouldBindYAML,这些⽅法使⽤ShouldBindWith。如果存在绑定错误,则返回错误,开发⼈员有责任适当地处理请求和错误
ShouldBindWith 请求数据映射示例
在使用映射时要创建对应结构体,例如:(注意点:binding:"required"表示必须的,如果不传,解析映射时会报错)
type Login struct {
User string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`
Password string `form:"password" json:"password" uri:"password"xml:"password" binding:"required"`
Age int `form:"age" binding:"required,gt=10"`
Name string `form:"name" binding:"required"`
Birthday time. Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"`
}
在不知道调用方传递的数据类型情况下使用ShouldBind()方法进行解析,示例
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
type Login struct {
User string `form:"username" json:"user" uri:"user" xml:"user"binding:"required"`
Password string `form:"password" json:"password" uri:"password"xml:"password" binding:"required"`
}
func main ( ) {
router := gin. Default ( )
router. POST ( "/loginJSON" , JsonFunc)
router. Run ( ":8080" )
}
func JsonFunc ( c * gin. Context) {
var login Login
if err := c. ShouldBind ( & login) ; err != nil {
c. JSON ( http. StatusBadRequest, gin. H{ "error" : err. Error ( ) } )
return
}
c. JSON ( http. StatusOK, gin. H{ "status" : "you are logged in" } )
}
注意点ShouldBind()查看源码,该方法只支持一下类型,根据Content-Type请求头,获取到指定类型后,按照指定格式获取参数进行绑定调用 ShouldBindWith()方法
func ( c * Context) ShouldBind ( obj interface { } ) error {
b := binding. Default ( c. Request. Method, c. ContentType ( ) )
return c. ShouldBindWith ( obj, b)
}
func Default ( method, contentType string ) Binding {
if method == http. MethodGet {
return Form
}
switch contentType {
case MIMEJSON:
return JSON
case MIMEXML, MIMEXML2:
return XML
case MIMEPROTOBUF:
return ProtoBuf
case MIMEMSGPACK, MIMEMSGPACK2:
return MsgPack
case MIMEYAML:
return YAML
case MIMEMultipartPOSTForm:
return FormMultipart
default :
return Form
}
}
如果明确调用方传递的数据类型,可以直接调用ShouldBindXXX()对应该类型的指定方法进行解析,例如ShouldBindJSON()
if err := c. ShouldBindJSON ( & login) ; err != nil {
c. JSON ( http. StatusBadRequest, gin. H{ "error" : err. Error ( ) } )
return
}
c. ShouldBindXML ( & login)
c. ShouldBindYAML ( & login)
c. ShouldBindHeader ( & login)
c. ShouldBindQuery ( & login)
c. ShouldBindUri ( & login)
5.gin内部整合了validator库go validator数据校验示例 使⽤绑定⽅法时,可以指定参数校验格式,例如使用 binding:“required” 修饰非空等等
ShouldBindHeader 将请求头绑定到一个结构体或接口示例
可以使用c.ShouldBindHeader方法来将请求头绑定到一个结构体或接口,并使用标签来指定绑定规则
func main ( ) {
r := gin. Default ( )
type Header struct {
UserID string `header:"User-ID"`
Token string `header:"Token"`
ClientIP string `header:"Client-IP"`
}
r. GET ( "/info" , func ( c * gin. Context) {
var header Header
if err := c. ShouldBindHeader ( & header) ; err != nil {
c. String ( 400 , err. Error ( ) )
c. Abort ( )
return
}
MustBindWith 方式
与前面的一样也要先创建接收数据对应的结构体变量 不同的是如果解析失败会panic 示例
func JsonFunc ( c * gin. Context) {
var login Login
if err := c. Bind ( & login) ; err != nil {
c. JSON ( http. StatusBadRequest, gin. H{ "error" : err. Error ( ) } )
return
}
if login. User != "ls" || login. Password != "123456" {
c. JSON ( http. StatusUnauthorized, gin. H{ "status" : "unauthorized" } )
return
}
c. JSON ( http. StatusOK, gin. H{ "status" : "you are logged in" } )
}
c. BindJSON ( & login)
c. BindXML ( & login)
c. BindYAML ( & login)
... ... 等等