go-gin-api 规划目录和参数验证(二)

摘要:
概述首先,同步项目概述:上一篇文章分享了项目是使用gomodules初始化的。在本文中,让我们分享:规划目录结构模型绑定和验证自定义验证器,制定API返回结构。规划目录结构|-go-gin api│О-应用程序│ О-config//配置文件│О-配置。去│ О-控制器//控制器层│О-参数绑定│├─参数_验证│├─

概述

首先同步下项目概况:

go-gin-api 规划目录和参数验证(二)第1张

上篇文章分享了,使用 go modules 初始化项目,这篇文章咱们分享:

    规划目录结构

    模型绑定和验证

    自定义验证器

    制定 API 返回结构

废话不多说,咱们开始吧。

规划目录结构

 

  ├─ go-gin-api    
    │  ├─ app    
    │     ├─ config           //配置文件    
    │        ├─ config.go    
    │     ├─ controller       //控制器层    
    │        ├─ param_bind    
    │        ├─ param_verify    
    │        ├─ ...    
    │     ├─ model            //数据库ORM    
    │        ├─ proto    
    │        ├─ ...    
    │     ├─ repository       //数据库操作层    
    │        ├─ ...    
    │     ├─ route            //路由    
    │        ├─ middleware    
    │        ├─ route.go    
    │     ├─ service          //业务层    
    │        ├─ ...    
    │     ├─ util             //工具包    
    │        ├─ ...    
    │  ├─ vendor  //依赖包    
    │     ├─ ...    
    │  ├─ go.mod    
    │  ├─ go.sum    
    │  ├─ main.go //入口文件



上面的目录结构是我自定义的,大家也可以根据自己的习惯去定义。

controller 控制器层主要对提交过来的数据进行验证,然后将验证完成的数据传递给 service 处理。

在 gin 框架中,参数验证有两种:

1、模型绑定和验证。

2、自定义验证器。

其中目录 param_bind,存储的是参数绑定的数据,目录 param_verify 存储的是自定义验证器。

接下来,让咱们进行简单实现。

模型绑定和验证

比如,有一个创建商品的接口,商品名称不能为空。

配置路由(route.go):

 

  ProductRouter := engine.Group("")    
    {    
        // 新增产品    
        ProductRouter.POST("/product", product.Add)    
        // 更新产品    
        ProductRouter.PUT("/product/:id", product.Edit)    
        // 删除产品    
        ProductRouter.DELETE("/product/:id", product.Delete)    
        // 获取产品详情    
        ProductRouter.GET("/product/:id", product.Detail)    
    }


参数绑定(param_bind/product.go):

 

   type ProductAdd struct {    
        Name string `form:"name" json:"name" binding:"required"`    
    }


控制器调用(controller/product.go):

  

 if err := c.ShouldBind(&param_bind.ProductAdd{}); err != nil {    
        utilGin.Response(-1, err.Error(), nil)    
        return    
    }



咱们用 Postman 模拟 post 请求时,name 参数不传或传递为空,会出现:

Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'required' tag

这说明使用到了参数设置的 binding:"required"。

那么还能使用 binding 哪些参数,有文档吗?

有。Gin 使用 go-playground/validator.v8 进行验证,相关文档:

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

接下来,咱们实现一下自定义验证器。

自定义验证器

比如,有一个创建商品的接口,商品名称不能为空并且参数名称不能等于 admin。

类似于这种业务需求,无法 binding 现成的方法,需要我们自己写验证方法,才能实现。

自定义验证方法(param_verify/product.go)

    func NameValid (    
        v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,    
        field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,    
    ) bool {    
        if s, ok := field.Interface().(string); ok {    
            if s == "admin" {    
                return false    
            }    
        }    
        return true    
    }



参数绑定(param_bind/product.go):

    type ProductAdd struct {    
        Name string `form:"name" json:"name" binding:"required,NameValid"`    
    }


同时还要绑定验证器:

 

   // 绑定验证器    
    if v, ok := binding.Validator.Engine().(*validator.Validate); ok {    
        v.RegisterValidation("NameValid", param_verify.NameValid)    
    }


咱们用 Postman 模拟 post 请求时,name 参数不传或传递为空,会出现:

Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'required' tag

name=admin 时:

Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'NameValid' tag

OK,上面两个验证都生效了!

上面的输出都是在控制台,能不能返回一个 Json 结构的数据呀?

能。接下来咱们制定 API 返回结构。

制定 API 返回结构

 

   {    
        "code": 1,    
        "msg": "",    
        "data": null    
    }

 这里我还准备了一分学习图和资料,如下:

go-gin-api 规划目录和参数验证(二)第2张

链接:https://pan.baidu.com/s/1v5gm7n0L7TGyejCmQrMh2g 提取码:x2p5

免费分享,但是X度限制严重,如若链接失效点击链接或搜索加群 群号518475424



API 接口的返回的结构基本都是这三个字段。

比如 code=1 表示成功,code=-1 表示失败。

msg 表示提示信息。

data 表示返回的数据。

那么,我们怎么在 gin 框架中实现它?

其实很简单 基于 c.JSON() 方法进行封装即可,直接看代码。

 

   package util    
    import "github.com/gin-gonic/gin"    
    type Gin struct {    
        Ctx *gin.Context    
    }    
    type response struct {    
        Code     int         `json:"code"`    
        Message  string      `json:"msg"`    
        Data     interface{} `json:"data"`    
    }    
    func (g *Gin)Response(code int, msg string, data interface{}) {    
        g.Ctx.JSON(200, response{    
            Code    : code,    
            Message : msg,    
            Data    : data,    
        })    
        return    
    }



控制器调用(controller/product.go):

 

  utilGin := util.Gin{Ctx:c}    
    if err := c.ShouldBind(&param_bind.ProductAdd{}); err != nil {    
        utilGin.Response(-1, err.Error(), nil)    
        return    
    }



咱们用 Postman 模拟 post 请求时,name 参数不传或传递为空,会出现:

    {    
        "code": -1,    
        "msg": "Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'required' tag",    
        "data": null    
    }
name=admin 时:

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


OK,上面两个验证都生效了!

免责声明:文章转载自《go-gin-api 规划目录和参数验证(二)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Kubernetes 使用 Kubevirt 运行管理 Windows 10 操作系统共享文件夹切换用户、局域网共享切换用户的方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

vue 使用字典值及其翻译

在日常开发中,我们会遇到很多枚举的值,这么枚举出来的值,我们可以统一处理,称为字典值的使用及翻译。 比如说:需要提交表单,表单中有性别和国家选项,这就需要下拉选择框来实现。数据少一点的还可以直接手写,但是像国家城市这种比较多的,手写就不太友好了。这个时候需要后端通过某个接口返回这个枚举值。我们使用这个返回的列表。 翻译就是枚举值对应的汉字与状态码,对照使用...

logstash5安装并实现mariadb数据写入到elasticsearch

java环境这里默认安装了 ,一般源码安装,这里就不说了 一、安装logstash 安装logstash可以用yum安装,也可以用源码安装: yum安装: 1.导入GPG: rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch 2.创建repo文件,vim /etc/yum.repo...

Angularjs总结(三)摸态框的使用

静态页面: <input class="btn btnStyle "value="提&emsp;取"type="button"ng-click="TQZJDFG() " /> controllers中的方法: 1 $scope.TQZJDFG = function() { 2 //可以将此参数传递到所弹出的摸态框的控制器中 3...

Swift开发中 JSON对象/JSON字符串/Data的互转

本文将介绍Swift开发中常用的转换(JSON对象/JSON字符串/Data之间的互相转换) #pragma mark - JSON(对象)----->JSON字符串 1、原生方法 //JSON--->data--->JSON字符串 let data = try?JSONSerialization.data(withJSONObject:...

[django]l利用xlrd实现xls文件导入数据

代码: #coding:utf-8 import os os.environ.setdefault("DJANGO_SETTINGS_MODULE", "www.settings") ''' Django 版本大于等于1.7的时候,需要加上下面两句 import django django.setup() 否则会抛出错误 dja...

小程序:前端防止用户重复提交&amp;amp;即时消息(IM)重复发送问题解决

背景: 最近参与开发的小程序,涉及到即时消息(IM)发送的功能; 聊天界面如下,通过键盘上的【发送】按钮,触发消息发送功能 问题发现: 功能开发完毕,进入测试流程;测试工程师反馈说: 在Android手机上,在极短的时间内频繁点击键盘上的【发送】按钮,消息会重复发送;IOS上该问题不太明显 本以为是普通的防重复提交问题,于是自然想到通过设定flag/js...