【Go】gin框架的ShouldBindQuery与BindQuery的区别

前言

Gin文档地址:https://gin-gonic.com/zh-cn/docs/examples/binding-and-validation/

使用gin框架进行模型绑定时,似乎使用两种绑定方法都可以,我很好奇ShouldBindQuery与BindQuery的区别,于是查了一下资料,果然是自己没有好好看文档。

Gin提供了两类绑定方法:

  • Must bind
    • Methods - Bind, BindJSON, BindXML, BindQuery, BindYAML
    • Behavior - 这些方法属于 MustBindWith 的具体调用。 如果发生绑定错误,则请求终止,并触发 c.AbortWithError(400, err).SetType(ErrorTypeBind)。响应状态码被设置为 400 并且 Content-Type 被设置为 text/plain; charset=utf-8。 如果您在此之后尝试设置响应状态码,Gin会输出日志 [GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 422。 如果您希望更好地控制绑定,考虑使用 ShouldBind 等效方法。
  • Should bind
    • Methods - ShouldBind, ShouldBindJSON, ShouldBindXML, ShouldBindQuery, ShouldBindYAML
    • Behavior - 这些方法属于 ShouldBindWith 的具体调用。 如果发生绑定错误,Gin 会返回错误并由开发者处理错误和请求。

ShouldBindQuery与BindQuery测试

测试代码

type Student struct {
   Name string `binding:"required"` //注意此处添加了binding注解,便于测试
}

func main() {
   r := gin.Default()
    
   //使用ShouldBindQuery
   r.GET("/student1", func(c *gin.Context) {
      var student Student
      if err := c.ShouldBindQuery(&student); err != nil {
         c.JSON(http.StatusOK, gin.H{"msg": "fail"})
      } else {
         fmt.Println(student)
         c.JSON(http.StatusOK, gin.H{"msg": "success"})
      }
   })
    
   //使用BindQuery
   r.GET("/student2", func(c *gin.Context) {
      var student Student
      if err := c.BindQuery(&student); err != nil {
         c.JSON(http.StatusOK, gin.H{"msg": "success"})
      } else {
         c.JSON(http.StatusOK, gin.H{"msg": "fail"})
      }
   })
    
   r.Run(":8080")
}

测试结果

访问使用ShouldBindQuery绑定的url:

1

访问使用BindQuery绑定的url:

2

可以注意到,使用BindQuery绑定模型时,如果发生绑定错误,则会自动返回400响应状态码,并且Content-Type 被设置为 text/plain; charset=utf-8,这也就是响应的body看起来与ShouldBindQuery不一样的原因。

BindQuery和ShouldBindQuery源码分析

// BindQuery is a shortcut for c.MustBindWith(obj, binding.Query).
func (c *Context) BindQuery(obj interface{}) error {
   return c.MustBindWith(obj, binding.Query)
}

// MustBindWith binds the passed struct pointer using the specified binding engine.
// It will abort the request with HTTP 400 if any error occurs.
// See the binding package.
func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error {
	if err := c.ShouldBindWith(obj, b); err != nil {
		c.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) // nolint: errcheck
		return err
	}
	return nil
}

// ShouldBindQuery is a shortcut for c.ShouldBindWith(obj, binding.Query).
func (c *Context) ShouldBindQuery(obj interface{}) error {
	return c.ShouldBindWith(obj, binding.Query)
}

从源码可以看出,BindQuery底层调用了MustBindWith,而MustBindWith调用了ShouldBindWith,因此BindQuery本质上是对ShouldBindQuery再封装。

总结

相同点:都能够将参数与模型进行绑定,操作方法一致。

不同点:当绑定发生错误时(如参数输入错误),BindQuery会自动返回400状态码并将Content-Type 被设置为 text/plain; charset=utf-8,ShouldBindQuery则不会。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值