使用gin搭建api后台系统之获取请求参数
上一篇记录了gin框架的搭建与路由的基本使用,本文主要记录一下路由处理过程中的参数传递问题,包含GET与POST传参,以及路径参数的使用。
GET 参数的获取
get 请求的参数写在url 中, 如 http://xxxx.com/path?id=1234&name=Manu&value=*111
gin 框架获取get参数主要有以下方法:
- func (c *Context) Query(key string) string
- func (c *Context) DefaultQuery(key, defaultValue string) string
- func (c *Context) GetQuery(key string) (string, bool)
写一个处理类:
func (user) Get(c *gin.Context) {
name := c.Query("name")
c.JSON(200, gin.H{"msg": "Hello User:"+ name})
}
当正常访问路由时,如 /name=yyx 时,会返回 msg: "Hello User: yyx", 如果不加name 参数,则name 为空字符串,返回 msg: "Hello User:"
有时我们需要在没有传参数的时候,有个默认的参数,那么此时就会用到DefaultQuery 方法
func (user) Get(c *gin.Context) {
name := c.DefaultQuery("name", "yyx")
c.JSON(200, gin.H{"msg": "Hello User:"+ name})
}
这时如果不传name 参数的话,则会以默认的 yyx 代替。
Query 与DefaultQuery 底层都是调用的GetQuery 方法,GetQuery 方法的第二个返回值,表示想要获取的参数是否存在,有了这个参数我们就可以做一些判断
func (user) Get(c *gin.Context) {
if name, ok := c.GetQuery("name"); ok{
c.JSON(200, gin.H{"msg": "Hello User:"+ name})
}else{
c.JSON(200, gin.H{"msg": "name 参数缺失"})
}
}
POST 参数的获取
GET 获取参数还是比较简单的,POST方式传递的参数更加复杂。post 传参主要以 application/x-www-form-urlencoded和multipart/form-data, 这两种可以通过在header中设置Content-Type来设置类型。
与GET参数相对应,post 参数也有三种获取的方法
- func (c *Context) PostForm(key string) string
- func (c *Context) DefaultPostForm(key, defaultValue string) string
- func (c *Context) GetPostForm(key string) (string, bool)
大多数情况下使用的是application/x-www-form-urlencoded ,可以使用PostForm方法来接收
func (user) Post(c *gin.Context) {
name := c.PostForm("name")
c.JSON(200, gin.H{"msg": "hi,"+name})
}
如果没有传name参数的时候,可以设置一个默认值
func (user) Post(c *gin.Context) {
name := c.DefaultPostForm("name", "杨彦星")
c.JSON(200, gin.H{"msg": "hi,"+name})
}
也可以通过GetPostForm来判断参数是否存在
func (user) Post(c *gin.Context) {
if name,ok := c.GetPostForm("name"); ok{
c.JSON(200, gin.H{"msg": "hi,"+name})
}else{
c.JSON(200, gin.H{"msg": "参数缺失"})
}
}
参数与结构体进行绑定
以上的get或者是post 中获取参数值的方法都是一个一个的依次赋值,当参数比较多的时候会很麻烦,这时可以定义一个结构体,然后将参数绑定到结构中
如定义student 结构体
type student struct {
Name string `json:"name" form:"name"`
Age int `json:"age" form:"age"`
}
这里在定义结构体的时候,添加了tag,这样参数以json或者form的形式就都可以识别了
func (user) Post(c *gin.Context) {
s := student{}
if err := c.ShouldBind(&s); err==nil{
c.JSON(200, gin.H{"msg": "hi,"+s.Name})
}else{
c.JSON(200, gin.H{"msg": "参数缺失"})
}
}
可以使用postman来调用一下,下面是以json格式发送的请求

下面是以form的形式发送

使用结构体进行绑定的时候 ,如果没有传参数,是不会报错了,只是以对应类型的默认值来代替,以下当不传age参数的时候,值默认为0

restful 风格的url
restful 风格的url, 通常将资源信息写到url中,如 /user/:id , 这种情况不可能为每一个id都对添加路由,这时我们可以使用通配符路由
需要两步,第一步设置路由信息
func main() {
r := gin.Default()
userH:= handlers.NewUser()
userG := r.Group("/user")
userG.GET("/list", userH.Get)
userG.POST("/post", userH.Post)
userG.GET(":id/info", userH.Info) //这里设置通配符路由
r.Run(":8080")
}
这里设置:id 为要匹配的路由参数,然后在相应的处理类中获取id参数
func (user) Info(c *gin.Context) {
id := c.Param("id")
c.JSON(200, gin.H{"msg": "用户id为"+id})
}
当然还可以设置多个参数 userG.GET(":name/:age/info", userH.Infos)
但是这种路由参数需要注意一些问题,如果定义了如下的路由
userG.GET(":name/:age/info", userH.Infos)
userG.GET(":id/infos", userH.Info)
那么将启动失败,提示 panic: ':id' in new path '/user/:id/infos' conflicts with existing wildcard ':name' in existing prefix '/user/:name'
它按照上面的路径进行匹配,发现 name和id处于相同的位置 ,所以会提示id这个参数不能再被定义了,也就是说某一位置的参数只能定义一次,不能重复定义。
第二个问题,你可以定义如下的路由
userG.GET("abc:id/infos", userH.Info) 那么在路径匹配上,则可以匹配 /abc10/infos ,id则为10,不加abc字符串,则无法匹配。
以上为记录一些gin框架上获取参数的常用方法,但是还有一些问题,如在参数匹配过程中,如果要求age参数为int值,且在0-100之间,则目前还没法校验,只能在相应的处理类中去做判断,接下来的文章将记录一下参数校验器的使用。
