hincky的主页 hincky的主页
  • 学习笔记

    • Vue笔记
    • Vuepress
    • nginx
  • 语言类

    • java
    • go
    • python
    • 设计模式
  • 框架类

    • Spring
    • Spring Security
    • Mybatis
  • 容器技术

    • docker
    • k8s
    • helm
    • prometheus
    • grafana
    • jenkins
  • 命令集合

    • linux命令
    • docker命令
    • git命令
    • vim命令
    • k8s命令
  • 数据库

    • sql
    • mysql
  • 协议

    • 网络模型
    • http/1.1
    • WebSocket
    • http/2
    • TLS/SSL
    • tcp
    • IP
    • tcpdump抓包命令
    • wireshark抓包工具
  • 通用

    • Git
  • 技术分享

    • git push/pull总是超时怎么办
    • idea debug技巧
    • postman使用
    • 问题总结
    • idea使用技巧
  • Oauth2

    • Oauth2原理
  • 项目列表

    • redis项目
    • 微服务项目
  • 分类
  • 标签
  • 归档
  • 随笔
GitHub (opens new window)

Hincky

当有趣的人,做想做的事
  • 学习笔记

    • Vue笔记
    • Vuepress
    • nginx
  • 语言类

    • java
    • go
    • python
    • 设计模式
  • 框架类

    • Spring
    • Spring Security
    • Mybatis
  • 容器技术

    • docker
    • k8s
    • helm
    • prometheus
    • grafana
    • jenkins
  • 命令集合

    • linux命令
    • docker命令
    • git命令
    • vim命令
    • k8s命令
  • 数据库

    • sql
    • mysql
  • 协议

    • 网络模型
    • http/1.1
    • WebSocket
    • http/2
    • TLS/SSL
    • tcp
    • IP
    • tcpdump抓包命令
    • wireshark抓包工具
  • 通用

    • Git
  • 技术分享

    • git push/pull总是超时怎么办
    • idea debug技巧
    • postman使用
    • 问题总结
    • idea使用技巧
  • Oauth2

    • Oauth2原理
  • 项目列表

    • redis项目
    • 微服务项目
  • 分类
  • 标签
  • 归档
  • 随笔
GitHub (opens new window)
  • java

  • python

  • Spring

  • SpringMVC

  • SpringSecurity

  • Mybatis

  • 设计模式

  • Go

    • 基础语法

    • Gin框架

    • Go gRPC

    • go-gin-api [文档]

      • 使用 go modules 初始化项目
        • 概述
        • 初始化
        • 添加依赖包
        • go mod 命令
        • 小结
        • 源码地址
      • 规划项目目录和参数验证
        • 概述
        • 规划目录结构
        • 模型绑定和验证
        • 自定义验证器
        • 制定 API 返回结构
        • 源码地址
        • go-gin-api 系列文章
        • 备注
      • 路由中间件 - 日志记录
        • 概述
        • gin.Logger()
        • 自定义 Logger()
        • 源码地址
        • go-gin-api 系列文章
      • 路由中间件 - 捕获异常
        • 概述
        • 什么是异常?
        • 怎么捕获异常?
        • 封装发邮件方法
        • 自定义邮件模板
        • 封装一个中间件
        • 备注
        • 源码地址
        • go-gin-api 系列文章
      • 路由中间件 - 链路追踪(Jaeger)
        • 概述
        • 如何设计日志记录?
        • 开源工具
        • Jaeger 架构图
        • Jaeger Span
        • Jaeger 部署
        • Jaeger 端口
        • Jaeger 采样率
        • Jaeger 缺点
        • 实战
        • 源码地址
        • go-gin-api 系列文章
      • 路由中间件 - 链路追踪(Jaeger)实战
        • 概述
        • Jaeger 部署
        • 准备测试服务
          • 听(listen)
          • 说(speak)
          • 读(read)
          • 写(write)
          • 唱(sing)
        • 应用示例
          • 实例化 Tracer
          • HTTP 注入
          • HTTP 拦截
          • gRPC 注入
          • gRPC 拦截
        • 运行
          • 启动服务
          • 访问路由
        • 效果
        • API 源码地址
        • Service 源码地址
        • go-gin-api 系列文章
      • 路由中间件 - 签名验证
        • 概览
        • MD5 组合
          • 生成签名
          • 验证签名
          • 中间件 - 代码实现
        • AES 对称加密
          • 生成签名
          • 验证签名
          • 中间件 - 代码实现
        • RSA 非对称加密
          • 创建签名
          • 验证签名
          • 中间件 - 代码实现
        • 如何调用?
        • 性能测试
          • MD5
          • AES
          • RSA
        • PHP 与 Go 加密方法如何互通?
        • 源码地址
        • go-gin-api 系列文章
    • go基本介绍
      • 安装go
      • hello world
      • 变量类型
      • 变量和声明
        • 定义和赋值分开
        • 定义和赋值合并
        • 最简单的写法
        • 最简写法结合函数
        • 多个变量同时赋值
        • 变量总结
      • if
      • 导入包
      • 运行go代码
      • 函数声明
        • 返回值个数
        • 参数接收
        • 两个参数都接收
        • 只接收其中一个参数
    • Go结构体
      • 定义结构体
      • 声明和初始化
        • 结构体字段
        • 结构体初始化
        • 函数参数传递方式
        • 镜像复制
        • 指针
      • 结构体上的函数
      • 构造器
        • new
    • Go相关项目推荐
      • 收录golang的一些好的开源项目
  • 后端
  • Go
  • go-gin-api [文档]
hincky
2022-11-21
目录

规划项目目录和参数验证

# 概述

首先同步下项目概况:

上篇文章分享了,使用 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 //入口文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

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

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)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

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

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

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

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

咱们用 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
}
1
2
3
4
5
6
7
8
9
10
11

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

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

同时还要绑定验证器:

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

咱们用 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
}
1
2
3
4
5

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
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

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

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

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

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

name=admin 时:

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

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

# 源码地址

https://github.com/xinliangnote/go-gin-api

# go-gin-api 系列文章

  • 1. 使用 go modules 初始化项目 (opens new window)

# 备注

Gin 模型验证 Validator 升级:validator.v8 升级为 validator.v9,已提交到 github !!!

编辑 (opens new window)
使用 go modules 初始化项目
路由中间件 - 日志记录

← 使用 go modules 初始化项目 路由中间件 - 日志记录→

最近更新
01
人生前期重要的能力
05-17
02
防火墙命令
04-11
03
docker-compose部署mysql主从集群
03-22
更多文章>
Theme by Vdoing | Copyright © 2022-2023 Hincky | MIT License | 粤ICP备2022120427号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式