go gin 框架下的数据解析与绑定

技术概述

本博客介绍使用gin框架完成基础的数据解析与绑定功能,以及列举出一些比较容易踩的坑。主要内容包括:json数据解析与绑定,表单数据解析与绑定,url数据解析与绑定

技术详述

1. json数据解析与绑定

先看官方文档中的源代码:

// 定义接收数据的结构体
type Login struct {
   User    string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`
   Pssword string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
}

func main() {
   r := gin.Default()
   // JSON绑定
   r.POST("loginJSON", func(c *gin.Context) {
      var json Login
      // 将request的body中的数据,自动按照json格式解析到结构体
      if err := c.ShouldBindJSON(&json); err != nil {
         // 返回错误信息
         // gin.H封装了生成json数据的工具
         c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
         return
      }
      // 判断用户名密码是否正确
      if json.User != "root" || json.Pssword != "admin" {
         c.JSON(http.StatusBadRequest, gin.H{"status": "304"})
         return
      }
      c.JSON(http.StatusOK, gin.H{"status": "200"})
   })
   r.Run(":8000")
}

这是一个简单的获取json中的账号密码,并进行验证的例子。从该例子中可以看出:

  • 获取json数据时不必通过输入json中每个key值来获得对应的数据
  • 结构体需要与获取json的格式相对应
  • 返回结果可以使用gin框架中封装的方法
  • post方法中需要一个与上下文(context)有关的参数,用于接收前端发来的json数据

于是,我们可以:

  1. 将service服务的结构体中的数据与需要从前端获取的参数一一对应,而删除掉多余的数据
  2. 声明一个函数用于json数据获取,解析与绑定,并调用相应的服务,将 c *gin.Context作为方程的参数
  3. 将service服务的结构体与接收的json进行绑定
  4. 调用service服务处理数据
  5. 返回结果

下面用一个比较完整的程序片段来阐述具体用法:

  • service结构体中的数据

    type CreateTeamService struct {
    	model.TeamRepositoryInterface // 声明了具体操作数据库创建团队的接口
    	Name          string `form:"name" json:"name" binding:"required"`
    	GroupLeaderID int    `form:"group_leader_id" json:"group_leader_id" binding:"required"`
    	ClassID       int    `form:"class_id" json:"class_id" binding:"required"`
    }
    
  • post方法响应请求

    	// 创建团队
    	v1.POST("team/create", api.CreateTeam)
    
  • json数据解析与绑定具体函数

    func CreateTeam(c *gin.Context) { // 该函数与CreateTeamService服务在不同的文件中
    	var service service.CreateTeamService
    	if err := c.ShouldBind(&service); err == nil {
            // 实例化接口
    		service.TeamRepositoryInterface = &model.Repo
    		res := service.CreateTeam()
    		c.JSON(http.StatusOK, res)
    	} else {
    		c.JSON(http.StatusOK, ErrorResponse(err))
    	}
    }
    

可以看出,大致过程与上述官方文档中的用例一致。

2. 表单数据解析和绑定

具体代码与json数据解析与绑定几乎完全一致,不同处仅仅在于将ShouldBindJSON()方法换成了Bind()方法。

这也是gin框架的强大之处,即面对不同的前端数据有统一的代码处理方法。其本质上,还是将表单数据中每个数据的key值与结构中的数据一一对应。

  • 表单结构示例

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
        <form action="http://localhost:8000/loginForm" method="post" enctype="application/x-www-form-urlencoded">
            用户名<input type="text" name="username"><br>
            密码<input type="password" name="password">
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    
  • 结构体示例

    type Login struct {
        // binding:"required"修饰的字段,若接收为空值,则报错,是必须字段
        User    string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`
        Pssword string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
    }
    

3. URI数据解析和绑定

具体代码与上述两种方式大致相同,同样地,需要将ShouldBindJSON()方法换成ShouldBindUri方法。

除此之外,需要注意获取api参数的方法,在此仅介绍最简单的一种方法:

  • 获取api参数代码

    (测试url:localhost:8080/user/乌鸡/805376577.com

     r.GET("/user/:name/*action", func(c *gin.Context) {
            name := c.Param("name")
            action := c.Param("action")
            //截取/
            action = strings.Trim(action, "/")
            c.String(http.StatusOK, name+" is "+action)
        })
    

输出结果:乌鸡 is 805376577.com

注意事项&最佳实践

  1. 一定要在使用service服务的函数中实例化结构体中的接口,不然会报空指针的错误
  2. 注意结构体中的数据类型,严格按照接口文档中的数据类型设计,同时,在“json”或“form“属性中填入相应的”key“值,做到一一对应
  3. 一定要在接收数据时加入判错处理
  4. 最好不要在一个函数中调用两个service服务(实际上也很难做到)
  5. 返回给前端的结果可以考虑用http.StatusOK替代200

总结

gin框架给代码的编写带来了诸多方便,不仅代码简单友好,并且在程序出错的情况下也可以通过报错快速找到解决措施,因为gin的报错都很详细,我推荐使用go语言可以多多使用gin框架。

虽然网上gin的官方文档都介绍的比较详细,但是关于gin的个人教程以及问答帖子在国内的数量比较少,所以有时候出了问题比较难在网上直接找到解决方法。好在gin语法简单,只要有一定编程基础,应该都能够独立解决大部分问题。

参考文档

http://www.topgoer.com/gin框架/gin路由/api参数.html

posted @ 2021-06-28 08:26  福贵的老牛  阅读(678)  评论(0编辑  收藏  举报