MustBind和ShouldBind
gin有两套参数绑定的方法:MustBind和ShouldBind,直接放上官方文档截图
两者最明显的区别就是,MustBind会将响应状态码设置为400,而ShouldBind不会。
一般项目中都是使用ShouldBind,因为这样更灵活,本文也只介绍ShouldBind这一套。
ShoudBind
ShouldBind这一套提供了ShouldBind、ShouldBindJSON、ShouldBindQuery…等函数,那他们有啥区别?什么场景用哪个?接下来通过源码来简单了解下。
区别和作用
对比截图
分析
首先从注释就可以了解到,ShouldBind方法会根据请求头的Content-Type字段来决定绑定引擎,来把参数解析到结构体指针。“application/json”使用json绑定引擎,“application/xml”使用xml绑定引擎。对比一下ShouldBind和ShouldBindJSON、ShouldBindQuery可以发现,在调用ShouldBindWith的时候,对于第二个参数来说,ShouldBind是传入经过Default函数处理后得到的绑定引擎,而另外两个方法是直接决定了绑定引擎。
结论
到这里其实就可以理解这几个函数的不同之处和作用了。ShouldBind根据Content-Type决定绑定引擎,ShouldBindJSON等函数则是指定了绑定引擎。
底层方法
ShouldBindWith
ShouldBindWith是参数绑定的底层函数,为ShouldBind这一套所有绑定参数方法调用。那么就来简单分析一下它的设计。
ShouldBindWith的第二个参数是Binding接口,这意味着实现了这个接口方法的结构体都可以作为参数传入。既然ShouldBindWith可以用多种绑定引擎来实现绑定参数,那么绑定引擎这个参数是接口类型也是理所应当的了。
Bind
Binding接口的Bind方法,就是实现参数绑定的核心,目前有十二种绑定引擎可用。
不同的绑定引擎有不同的实现,接下来以JSON为例来分析。
Bind方法首先判断请求是否有效,若请求或请求体其中有一个为nil,则请求无效,返回错误。当请求有效,则由decodeJSON进行参数解码。
decodeJSON函数直接看最后两行代码,从命名可以猜测到decoder.Decode就是解码json绑定参数到obj,validate是对obj对应的具体类型进行校验。至于更具体的分析,本文就不做阐述了。
Default
回过头来分析一下这个Default函数
这个函数通过switch关键字来匹配Content-Type字段的值,返回对应的实现了接口的结构体。如果Content-Type的值为“application/json”,那就会与MIMEJSON相匹配,返回jsonBinding结构体。
匹配常量和返回常量的具体值如下图所示,其中最常用的是“application/json”、“multipart/form-data”
参数获取
path参数
单个参数获取
Param()函数
参数绑定
标签“uri”,搭配ShouldBindUri()函数
query参数
单个参数获取
对于只获取一个参数值的情况,gin提供了两种函数:DefaultQuery()和Query(),文档截图如下
参数绑定
当参数较多时,用Query()函数一个一个获取参数很低效,这时可以用模型绑定。要把query参数绑定到结构体上,需要使用标签“form”,搭配ShouldBine()函数。
form-data参数
单个参数获取
参数绑定
标签“form”,搭配ShouldBind()函数
json
标签“json”,搭配ShouldBind()或ShouldBindJSON()函数