概述

上篇文章分享了 Gin 框架使用 Logrus 进行日志记录,这篇文章分享 Gin 框架的数据绑定与验证。

有读者咨询我一个问题,如何让框架的运行日志不输出控制台?

解决方案:

  1. engine := gin.Default() //修改成如下
  2. engine := gin.New()

我是怎么知道的?看框架代码。

Default()

  1. func Default() *Engine {
  2. debugPrintWARNINGDefault()
  3. engine := New()
  4. engine.Use(Logger(), Recovery())
  5. return engine
  6. }

New() 代码我就不贴了。

我们看到 Default() 使用了两个中间件 Logger(), Recovery(),如果不想使用,那就直接使用 New() 就可以了。

开始今天的文章。

比如,请求 v1/member/add 新增会员方法,nameage 为必填,同时 name 不能等于 admin 字符串,10 <= age <= 120。

直接看代码吧。

首先,先定义一个结构体。

entity/member.go

  1. package entity
  2. // 定义 Member 结构体
  3. type Member struct {
  4. Name string `form:"name" json:"name" binding:"required,NameValid"`
  5. Age int `form:"age" json:"age" binding:"required,gt=10,lt=120"`
  6. }

binding 中 required,这个是框架自带的,NameValid,这个是自己定义的。

问题一:框架自带的 binding 参数还有哪些?

问题二:自定义验证方法,怎么写?

接下来要说的就是问题二,写一个验证方法。

validator/member/member.go

  1. package member
  2. import (
  3. "gopkg.in/go-playground/validator.v8"
  4. "reflect"
  5. )
  6. func NameValid(
  7. v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,
  8. field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,
  9. ) bool {
  10. if s, ok := field.Interface().(string); ok {
  11. if s == "admin" {
  12. return false
  13. }
  14. }
  15. return true
  16. }

接下来,在路由中绑定:

router/router.go

  1. package router
  2. import (
  3. "ginDemo/middleware/logger"
  4. "ginDemo/middleware/sign"
  5. "ginDemo/router/v1"
  6. "ginDemo/router/v2"
  7. "ginDemo/validator/member"
  8. "github.com/gin-gonic/gin"
  9. "github.com/gin-gonic/gin/binding"
  10. "gopkg.in/go-playground/validator.v8"
  11. )
  12. func InitRouter(r *gin.Engine) {
  13. r.Use(logger.LoggerToFile())
  14. // v1 版本
  15. GroupV1 := r.Group("/v1")
  16. {
  17. GroupV1.Any("/product/add", v1.AddProduct)
  18. GroupV1.Any("/member/add", v1.AddMember)
  19. }
  20. // v2 版本
  21. GroupV2 := r.Group("/v2").Use(sign.Sign())
  22. {
  23. GroupV2.Any("/product/add", v2.AddProduct)
  24. GroupV2.Any("/member/add", v2.AddMember)
  25. }
  26. // 绑定验证器
  27. if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
  28. v.RegisterValidation("NameValid", member.NameValid)
  29. }
  30. }

最后,看一下调用的代码。

router/v1/member.go

  1. package v1
  2. import (
  3. "ginDemo/entity"
  4. "github.com/gin-gonic/gin"
  5. "net/http"
  6. )
  7. func AddMember(c *gin.Context) {
  8. res := entity.Result{}
  9. mem := entity.Member{}
  10. if err := c.ShouldBind(&mem); err != nil {
  11. res.SetCode(entity.CODE_ERROR)
  12. res.SetMessage(err.Error())
  13. c.JSON(http.StatusForbidden, res)
  14. c.Abort()
  15. return
  16. }
  17. // 处理业务(下次再分享)
  18. data := map[string]interface{}{
  19. "name" : mem.Name,
  20. "age" : mem.Age,
  21. }
  22. res.SetCode(entity.CODE_ERROR)
  23. res.SetData(data)
  24. c.JSON(http.StatusOK, res)
  25. }

访问看看效果吧。

访问:http://localhost:8080/v1/member/add

  1. {
  2. "code": -1,
  3. "msg": "Key: 'Member.Name' Error:Field validation for 'Name' failed on the 'required' tag\nKey: 'Member.Age' Error:Field validation for 'Age' failed on the 'required' tag",
  4. "data": null
  5. }

访问:http://localhost:8080/v1/member/add?name=1

  1. {
  2. "code": -1,
  3. "msg": "Key: 'Member.Age' Error:Field validation for 'Age' failed on the 'required' tag",
  4. "data": null
  5. }

访问:http://localhost:8080/v1/member/add?age=1

  1. {
  2. "code": -1,
  3. "msg": "Key: 'Member.Age' Error:Field validation for 'Age' failed on the 'required' tag",
  4. "data": null
  5. }

访问:http://localhost:8080/v1/member/add?name=admin&age=1

  1. {
  2. "code": -1,
  3. "msg": "Key: 'Member.Name' Error:Field validation for 'Name' failed on the 'NameValid' tag",
  4. "data": null
  5. }

访问:http://localhost:8080/v1/member/add?name=1&age=1

  1. {
  2. "code": -1,
  3. "msg": "Key: 'Member.Age' Error:Field validation for 'Age' failed on the 'gt' tag",
  4. "data": null
  5. }

访问:http://localhost:8080/v1/member/add?name=1&age=121

  1. {
  2. "code": -1,
  3. "msg": "Key: 'Member.Age' Error:Field validation for 'Age' failed on the 'lt' tag",
  4. "data": null
  5. }

访问:http://localhost:8080/v1/member/add?name=Tom&age=30

  1. {
  2. "code": 1,
  3. "msg": "",
  4. "data": {
  5. "age": 30,
  6. "name": "Tom"
  7. }
  8. }

未避免返回信息过多,错误提示咱们也可以统一。

  1. if err := c.ShouldBind(&mem); err != nil {
  2. res.SetCode(entity.CODE_ERROR)
  3. res.SetMessage("参数验证错误")
  4. c.JSON(http.StatusForbidden, res)
  5. c.Abort()
  6. return
  7. }

这一次目录结构调整了一些,在这里说一下:

  1. ├─ ginDemo
  2. ├─ common //公共方法
  3. ├── common.go
  4. ├─ config //配置文件
  5. ├── config.go
  6. ├─ entity //实体
  7. ├── ...
  8. ├─ middleware //中间件
  9. ├── logger
  10. ├── ...
  11. ├── sign
  12. ├── ...
  13. ├─ router //路由
  14. ├── ...
  15. ├─ validator //验证器
  16. ├── ...
  17. ├─ vendor //扩展包
  18. ├── github.com
  19. ├── ...
  20. ├── golang.org
  21. ├── ...
  22. ├── gopkg.in
  23. ├── ...
  24. ├─ Gopkg.toml
  25. ├─ Gopkg.lock
  26. ├─ main.go

signlogger 调整为中间件,并放到 middleware 中间件 目录。

新增了 common 公共方法目录。

新增了 validator 验证器目录。

新增了 entity 实体目录。

具体代码我会放到 GitHub,有感兴趣的可以去看:https://github.com/xinliangnote/Go。

上面还遗漏了问题一没解决,框架自带的 binding 参数还有哪些?

从框架源码了解到验证使用的是:

gopkg.in/go-playground/validator.v8

文档地址为:

https://godoc.org/gopkg.in/go-playground/validator.v8

去探索文档吧,里面有很多验证规则。

推荐阅读

Gin 框架

基础篇

本文欢迎转发,转发请注明作者和出处,谢谢!

[系列] Gin框架 - 数据绑定和验证的更多相关文章

  1. Gin框架 - 数据绑定和验证

    概述 上篇文章分享了 Gin 框架使用 Logrus 进行日志记录,这篇文章分享 Gin 框架的数据绑定与验证. 有读者咨询我一个问题,如何让框架的运行日志不输出控制台? 解决方案: engine : ...

  2. Gin框架 - 自定义错误处理

    目录 概述 错误处理 自定义错误处理 panic 和 recover 推荐阅读 概述 很多读者在后台向我要 Gin 框架实战系列的 Demo 源码,在这里再说明一下,源码我都更新到 GitHub 上, ...

  3. gin框架中的参数验证

    结构体验证 用gin框架的数据验证,可以不用解析数据,减少if else,会简洁许多. 处理请求方法 func structValidator(context *gin.Context) { var ...

  4. 基于gin框架和jwt-go中间件实现小程序用户登陆和token验证

    本文核心内容是利用jwt-go中间件来开发golang webapi用户登陆模块的token下发和验证,小程序登陆功能只是一个切入点,这套逻辑同样适用于其他客户端的登陆处理. 小程序登陆逻辑 小程序的 ...

  5. Gin框架系列03:换个姿势理解中间件

    什么是中间件 中间件,英译middleware,顾名思义,放在中间的物件,那么放在谁中间呢?本来,客户端可以直接请求到服务端接口. 现在,中间件横插一脚,它能在请求到达接口之前拦截请求,做一些特殊处理 ...

  6. gin框架教程:代码系列demo地址

    gin框架教程代码地址: https://github.com/jiujuan/gin-tutorial demo目录: 01quickstart 02parameter 03route 04midd ...

  7. Gin框架系列02:路由与参数

    回顾 上一节我们用Gin框架快速搭建了一个GET请求的接口,今天来学习路由和参数的获取. 请求动词 熟悉RESTful的同学应该知道,RESTful是网络应用程序的一种设计风格和开发方式,每一个URI ...

  8. gin框架学习手册

    前言 gin框架是go语言的一个框架,框架的github地址是:https://github.com/gin-gonic/gin 转载本文,请标注原文地址:https://www.cnblogs.co ...

  9. Golang语言系列-17-Gin框架

    Gin框架 Gin框架简介 package main import ( "github.com/gin-gonic/gin" "io" "net/ht ...

随机推荐

  1. 逆向工程mybatis-geneator.xml

    <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE generatorConfiguration ...

  2. GO方法与接口

    Go语言没有沿袭传统面向对象编程中的诸多概念,比如继承.虚函数.构造函数和析构函数.隐藏的this指针等. 方法 Go 语言中同时有函数和方法.方法就是一个包含了接受者(receiver)的函数,re ...

  3. Angular4初学

    [1].在学习Angular4之前,首先要了解一些typescript的知识. 以下是我的总结:https://gitee.com/FangXiaoQi123/angularJSCeShi/blob/ ...

  4. python requests模块session的使用建议及整个会话中的所有cookie的方法

    话不多说,直接上代码 测试代码 服务端 下面是用flask做的一个服务端,用来设置cookie以及打印请求时的请求头 # -*- coding: utf-8 -*- from flask import ...

  5. win的cmd环境中设置***代理

    想在win的cmd环境中设置代理进行FQ安装软件,如npm等一系列. 1.配置好shadowsocks,然后编辑服务器,查看代理端口 2.打开win命令行cmd set http_proxy=http ...

  6. yii中常用路径

    //YII framework路径Yii::getFrameworkPath(); //protected/runtimeYii::app()->getRuntimePath(); //在vie ...

  7. jQuery入门——选择器

    jQuery选择器可以分为四类:基础选择器,层级选择器,属性选择器,过滤选择器 基础选择器: <!DOCTYPE html> <html> <head> <m ...

  8. 👮 Golang Gin/Ace/Iris/Echo RBAC 鉴权库

    GRBAC 项目地址: https://github.com/storyicon/grbac Grbac是一个快速,优雅和简洁的RBAC框架.它支持增强的通配符并使用Radix树匹配HTTP请求.令人 ...

  9. Singleton and Prototype Bean Scope in Spring

    Scope描述的是Spring容器如何新建Bean的实例的. 1> Singleton: 一个Spring容器只有一个Bean的实例,此为Spring的默认配置,全容器共享一个实例. 2> ...

  10. K Balanced Teams CodeForces - 1133E (Dp)

    题意: 给出 n 个数,选取其中若干个数分别组成至多 k 组,要求每组内最大值与最小值的差值不超过5,求最后被选上的总人数. 题解: 将a[1∼n] 从小到大排序, f[i][j] 表示到第 i 个数 ...