go-zero结合自定义模版校验前端参数

news2024/12/22 17:12:03

一、自定义模版的使用

如果想对官网goctl命名生成的项目结构改变的话,可以使用模版,自定义模版,然后生成自己想要的文件

  • 1、使用命令将官方模版映射到本地

    goctl template init
    
  • 2、在项目的根目录下添加文件夹,把刚刚映射到本地的拷贝到项目中

    在这里插入图片描述

  • 3、使用模版根据api文件来生成go的文件

    # 注意这个地方要根据你当前路径来找到goctl文件夹
    goctl api go -api *api --dir . --style=goZero --home ../../goctl
    
  • 4、注意

    • goctl api go -api *.api -dir . --style=gozero可以根据api文件来生成项目,也是修改了api来更新项目
    • goctl api new user是创建一个userapi项目

二、使用go-playground对前端数据校验

  • 1、安装依赖包

    go get -u github.com/go-playground/validator/v10
    
  • 2、在translator.go文件中自定义将错误翻译成中文

    package utils
    
    import (
    	"errors"
    	"github.com/go-playground/locales/zh"
    	ut "github.com/go-playground/universal-translator"
    	"github.com/go-playground/validator/v10"
    	zhTranslations "github.com/go-playground/validator/v10/translations/zh"
    	"go_zero_demo05/common/utils/validators"
    	"reflect"
    	"strings"
    )
    
    func Validate(dataStruct interface{}) error {
    	zhT := zh.New()
    	validate := validator.New()
    	// 注册一个函数,获取struct tag里自定义的label作为字段名
    	validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
    		name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
    		if name == "-" {
    			return ""
    		}
    		return name
    	})
    
    	uni := ut.New(zhT)
    	trans, _ := uni.GetTranslator("zh")
    	// 注册自定义结构体字段校验方法
    	// 1.注册时间要比当前的晚
    	if err := validate.RegisterValidation("checkAfterDate", validators.ValidateAfterDate); err != nil {
    		return err
    	}
    	if err := validate.RegisterTranslation(
    		"checkAfterDate",
    		trans,
    		registerTranslator("checkAfterDate", "{0} 必须要晚于当前日期"),
    		translate,
    	); err != nil {
    		return err
    	}
    	
    
    	// 验证器注册翻译器
    	if err := zhTranslations.RegisterDefaultTranslations(validate, trans); err != nil {
    		return err
    	}
    	err := validate.Struct(dataStruct)
    	if err != nil {
    		for _, err1 := range err.(validator.ValidationErrors) {
    			return errors.New(err1.Translate(trans))
    		}
    	}
    	return nil
    }
    
    // registerTranslator 为自定义字段添加翻译功能
    func registerTranslator(tag string, msg string) validator.RegisterTranslationsFunc {
    	return func(trans ut.Translator) error {
    		if err := trans.Add(tag, msg, false); err != nil {
    			return err
    		}
    		return nil
    	}
    }
    
    // translate 自定义字段的翻译方法
    func translate(trans ut.Translator, fe validator.FieldError) string {
    	msg, err := trans.T(fe.Tag(), fe.Field())
    	if err != nil {
    		panic(fe.(error).Error())
    	}
    	return msg
    }
    
  • 3、关于自定义校验方法

    package validators
    
    import (
    	"github.com/go-playground/validator/v10"
    	"time"
    )
    
    // ValidateAfterDate 判断时间是否是当前时间之后
    func ValidateAfterDate(fl validator.FieldLevel) bool {
    	date, err := time.Parse("2006-01-02", fl.Field().String())
    	if err != nil {
    		return false
    	}
    	if date.Before(time.Now()) {
    		return false
    	}
    	return true
    }
    
  • 4、自定义模版handler.tpl中添加前端参数校验的方法

    package {{.PkgName}}
    
    import (
    	"net/http"
    
    	"github.com/zeromicro/go-zero/rest/httpx"
    	{{.ImportPackages}}
    )
    
    func {{.HandlerName}}(svcCtx *svc.ServiceContext) http.HandlerFunc {
    	return func(w http.ResponseWriter, r *http.Request) {
    		{{if .HasRequest}}var req types.{{.RequestType}}
    		if err := httpx.Parse(r, &req); err != nil {
    			httpx.ErrorCtx(r.Context(), w, err)
                return
    		}
    		// 数据验证
            if validateErr := utils.Validate(&req);validateErr != nil {
                httpx.ErrorCtx(r.Context(), w, validateErr)
                return
            }
    		{{end}}l := {{.LogicName}}.New{{.LogicType}}(r.Context(), svcCtx)
    		{{if .HasResp}}resp, {{end}}err := l.{{.Call}}({{if .HasRequest}}&req{{end}})
    		if err != nil {
                httpx.ErrorCtx(r.Context(), w, err)
            } else {
                {{if .HasResp}}httpx.OkJsonCtx(r.Context(), w, resp){{else}}httpx.Ok(w){{end}}
            }
    	}
    }
    
  • 5、在定义api的时候加上参数校验

    type PostDemoReq {
    	Name string `json:"name" validate:"required"` // 姓名
    	Age  int64  `json:"age" validate:"required,gte=1,lte=130"` // 年龄
    	// optional 表示可选,omitempty如果为空的时候不走后面
    	Mobile         string `json:"mobile,optional" validate:"omitempty,checkMobile"` // 手机号码
    	Email          string `json:"email,optional" validate:"omitempty,checkEmail"` // 邮箱地址
    	Date           string `json:"date" validate:"omitempty,checkDate,checkAfterDate"` // 时间
    	Password       string `json:"password" validate:"required"` // 密码
    	ConfimPassword string `json:"confimPassword" validate:"eqfield=Password"` // 确认密码
    }
    
    • optional表示go-zero参数是可选,一个很大作用是生成的swagger上没有标识必填字段

    • checkMobilecheckEmailcheckAfterDate都是自定义校验器,需要在translator.go注册才能使用

    • omitempty表示如果为空的话,就不走后面的校验

      在这里插入图片描述

  • 6、使用命令用模版生成文件,注意导包的问题

    goctl api go -api *api --dir . --style=goZero --home ../../goctl
    
  • 7、自测错误,并且返回给前端

    在这里插入图片描述

  • 8、当go-zero中标识必填字段的时候提示的错误为下面,比如name字段不写的时候,age字段数据类型错误的时候
    在这里插入图片描述

  • 9、age数据类型错误的时候

    在这里插入图片描述

三、翻译go-zero中的参数错误

  • 1、自定义translatorError.go翻译文件

    package utils
    
    import (
    	"fmt"
    	"regexp"
    	"strings"
    )
    
    func TranslatorError(err error) string {
    	reg := regexp.MustCompile(`"(.*)?"`)
    	match := reg.FindString(err.Error())
    	if strings.Contains(err.Error(), "is not set") {
    		if match != "" {
    			return fmt.Sprintf("%s 为必填字段!", strings.Replace(match, `"`, "", -1))
    		}
    	} else if strings.Contains(err.Error(), "mismatch for field") {
    		if match != "" {
    			return fmt.Sprintf("%s 数据类型不对!", strings.Replace(match, `"`, "", -1))
    		}
    	}
    	return ""
    }
    
  • 2、在返回错误拦截器中添加使用

    func ErrHandler(name string) func(ctx context.Context, err error) (int, any) {
    	return func(ctx context.Context, err error) (int, any) {
    		fmt.Println(err, "错误信息")
    		causeErr := errors.Cause(err)
    		fmt.Println(causeErr, "111-->")
    		var errMessage = err.Error()
    		// 翻译错误
    		translatorError := TranslatorError(err)
    		if translatorError != "" {
    			errMessage = translatorError
    		}
    		// 日志记录
    		logx.WithContext(ctx).Errorf("【%s】 err %v", name, errMessage)
    		return http.StatusBadRequest, Fail(errMessage)
    	}
    }
    
  • 3、当年龄数据类型错误的时候

    在这里插入图片描述

  • 4、name字段没写的时候
    在这里插入图片描述

  • 5、另外name为空字符串的时候

    在这里插入图片描述

四、参考文档

  • 1、go-playground文档

  • 2、go-zero官网

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2036736.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

luckyexcel 编辑预览excel文件

luckyexcel 编辑预览excel文件 支持后端传文件流预览编辑&#xff0c;也支持选择本地文件编辑预览 看效果 上代码 <template><div style"margin: 30px"><div class"button-box2"><div><div style"color: red">…

【精通SDL之----SDL_RenderReadPixels截屏】

SDL_RenderReadPixels截屏 前言一、SDL_RenderReadPixels简介二、问题现象三、规避方案1. 离屏纹理2. ding! *灵光一现* 前言 最近使用SDL2在鸿蒙系统(Harmoney OS)上截取视频播放过程中的数据&#xff0c;发现捕获的数据为空&#xff0c;然在windows上却可以正常捕获&#xff…

Linux 内核源码分析---网络层分析

版本(version)&#xff1a;指定所用 IP 协议的版本&#xff0c;该字段有效值为 4 或 6&#xff1b; IP首部长度(IHL)&#xff1a;定义首部的长度&#xff0c;由于选项数量可变&#xff1b; 服务区分&#xff1a;用于更复杂协议选项&#xff1b; 长度&#xff1a;指定分组的总长…

AI技术重塑招聘流程

一、引言 随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;技术正以前所未有的速度渗透到社会的各个领域&#xff0c;其中&#xff0c;人力资源管理领域也不例外。在全员招聘这一关键环节中&#xff0c;AI技术的应用不仅极大地提高了招聘效率&#xff0c;还…

【Java数据结构】---Queue

乐观学习&#xff0c;乐观生活&#xff0c;才能不断前进啊&#xff01;&#xff01;&#xff01; 我的主页&#xff1a;optimistic_chen 我的专栏&#xff1a;c语言 &#xff0c;Java 欢迎大家访问~ 创作不易&#xff0c;大佬们点赞鼓励下吧~ 文章目录 前言队列Queue队列的模拟…

fme处理空间数据入门v0

概述 本教程是最最最基本的fme处理空间数据内容&#xff0c;给新同事介绍我以前是怎么干活用的&#xff0c;基本啥有用的东西。 本教程主要说如何在 FME Workbench中创建模板文件&#xff08;一般我们把fme写的工作空间就叫模板&#xff09;&#xff0c;教程里面主要是利用GI…

Linux2.6内核进程调度队列详细讲解

上图是 Linux2.6 内核中进程队列的数据结构&#xff0c;之间关系也已经给大家画出来&#xff0c;方便大家理解。 一个 CPU 拥有一个 runqueue。 Linux真正的调度方式是通过runqueue进行调度的&#xff0c;我们知道进程的优先级范围是根据nice值确定的&#xff0c;而nice值的范围…

怎么配置Datagrip中字体的大小,修改注释的颜色呢

新手刚安装Datagrip时&#xff0c;都会遇到怎么调字体大小的问题&#xff0c;接下来解决一下吧 具体步骤&#xff1a; 1.进入Datagrip的操作窗口后&#xff0c;点击左上方的菜单栏中file(文件)。 2.在文件中点击设置setting。 3.在设置窗口点击Editor,再点击Font。 4.在Fo…

.[[Hoeosi@airmail.cc]].rntc勒索病毒数据怎么处理|数据解密恢复

导言&#xff1a; 近年来&#xff0c;勒索病毒&#xff08;也称为勒索软件&#xff09;已成为网络安全领域的一大威胁。其中&#xff0c;.[[Hoeosiairmail.cc]].rntc勒索病毒作为一种新型恶意软件&#xff0c;通过加密用户的重要文件并要求支付赎金来解锁&#xff0c;给个人和…

深度学习 —— 个人学习笔记20(转置卷积、全卷积网络)

声明 本文章为个人学习使用&#xff0c;版面观感若有不适请谅解&#xff0c;文中知识仅代表个人观点&#xff0c;若出现错误&#xff0c;欢迎各位批评指正。 三十九、转置卷积 import torch from torch import nndef trans_conv(X, K):h, w K.shapeY torch.zeros((X.shape[…

Datawhale AI夏令营第四期魔搭- AIGC文生图方向 task02笔记

1 前言 本次是学习内容是Datawhale AI夏令营第四期-AIGC文生图方向的学习笔记。 2 AIGC简介 AIGC&#xff08;Artificial Intelligence Generated Content&#xff09;即人工智能生成内容&#xff0c;即人工智能通过学习大量的数据&#xff0c;来实现自动生成各种内容&#xf…

仿RabbitMQ实现消息队列

前言&#xff1a;本项目是仿照RabbitMQ并基于SpringBoot Mybatis SQLite3实现的消息队列&#xff0c;该项目实现了MQ的核心功能&#xff1a;生产者、消费者、中间人、发布、订阅等。 源码链接&#xff1a;仿Rabbit MQ实现消息队列 目录 前言&#xff1a;本项目是仿照Rabbi…

JVM运行时数据区之虚拟机栈

【1】概述 Java虚拟机栈&#xff08;Java Virtual Machine Stack&#xff09;&#xff0c;早期也叫Java栈。每个线程在创建时都会创建一个虚拟机栈&#xff0c;其内部保存一个个的栈帧&#xff08;Stack Frame&#xff09;&#xff0c;对应着一次次的Java方法调用。 栈是运行…

World of Warcraft [CLASSIC] 80 WLK [Gundrak] BUG

World of Warcraft [CLASSIC] 80 WLK [Gundrak] BUG 魔兽世界怀旧版&#xff0c;80级&#xff0c;5人副本古达克&#xff0c;科技队伍&#xff08;BUG队伍&#xff09; 副本有两个门口 这样看&#xff0c;是不是觉得很怪。是的&#xff0c;和图1刚好相反的。 因此应该翻转180…

24电赛H题总结

一、题目 题目链接&#xff1a;自动行驶小车&#xff08;H题&#xff09; 我们截取一些重要信息 1. 小车行驶场地示意图 2.要求 二、赛题分析 技术挑战与准备 MCU熟悉度&#xff1a;尽管TI MSPM0系列MCU在使用上类似于STM32CUBEIDEKeil&#xff0c;但其开发环境也需要熟悉。因…

数据结构入门——04栈

1.栈 栈是限制在一端进行插入操作和删除操作的线性表&#xff08;俗称堆栈&#xff09; 允许进行操作的一端称为“栈顶”&#xff0c;另一固定端称为“栈底”&#xff0c;当栈中没有元素时称为“空栈”。 栈的特点 &#xff1a;后进先出LIFO&#xff08;Last In First Out&a…

支持I2C接口、抗干扰性强、14通道触摸按键的电容式触摸芯片-GTX314L

电容式触摸芯片 - GTX314L是具有多通道触发传感器的14位触摸传感器系列&#xff0c;它是通过持续模式提供中断功能和唤醒功能&#xff0c;广泛适用于各种控制面板应用&#xff0c;可直接兼容原机械式轻触按键的处理信号。 GTX314L芯片内部采用特殊的集成电路&#xff0c;具有高…

C++进阶-智能指针

1. 为什么需要智能指针&#xff1f; 下面我们先分析一下下面这段程序有没有什么内存方面的问题&#xff1f;提示一下&#xff1a;注意分析MergeSort函数中的问题。 int div() {int a, b;cin >> a >> b;if (b 0)throw invalid_argument("除0错误");retur…

【C语言】内存管理

C语言-内存管理 一、C进程内存布局二、栈内存1、存储在栈内存中的参数有哪些&#xff1f;2、栈内存的特点&#xff1f; 三、静态数据四、数据段与代码段五、堆内存 一、C进程内存布局 \qquad 任何一个程序&#xff0c;正常运行都需要内存资源&#xff0c;用来存放诸如变量、常量…

第九届“创客中国”武汉区域赛正式启幕 灵途科技勇夺前三,晋级决赛!

8月8日&#xff0c;第九届“创客中国”武汉区域赛正式启幕&#xff0c;首场聚焦先进制造领域。灵途科技勇夺先进制造领域专场企业组前三名&#xff0c;成功晋级决赛。 “创客中国”大赛是工业和信息化部组织开展的双创赛事活动&#xff0c;以构建产业链协同发展为出发点&#…