【GoLang】利用validator包实现服务端参数校验时自定义错误信息

在C/S架构下,服务端在校验请求参数时,若出现参数错误,要响应给客户端一个错误消息,通常我们会统一响应"参数错误"。

但是,如果只是一味的提示参数错误,我并不知道具体是哪个参数错了呀!能不能有更详细,更细致的提示信息?例如(账号错误、密码为空、姓名不能包含数字),当然可以,下面我来教你如何利用validator包实现自定义参数错误信息。

validator包下载

validator是开源的第三方包,专门用于进行参数校验。我们先下载一下:

github.com/go-playground/validator/v10

打上结构体标签

validator包提供了结构体标签选项,我们可以为想要进行参数校验的字段打上标签,之后就会以此标签作为校验标准

进行参数校验

Struct方法会检验其参数s(假设参数s为结构体)是否符合结构体标签的标准(上文提到的validate标签)。若不符合标准,则将具体不符合的情况作为err返回。

现在我们模拟一遍请求参数错误时的场景

go 复制代码
package main

import (
	"fmt"
	"github.com/go-playground/validator/v10"
)

type RegisterModel struct {
	Username string `validate:"required,numeric"`               // numeric 必须是数字
	Password string `validate:"required,alphanum"`              // alphanum 必须是数字字母组合
	Name     string `validate:"required"`                       // required 必须非空
	Age      int    `validate:"required,gte=0,lte=100,numeric"` // gte, lte 为最大最小值
	Gender   string `validate:"required,oneof=男 女"`             // oneof 必须为其中的某个值
}

func main() {
	// 模拟客户端发来的请求参数
	model := RegisterModel{
		Username: "中文中文",	// 故意让其不符合标准
		Password: "123哈哈哈",
		Name:     "",
	}

	// 用validator包进行校验
	validate := validator.New()	// 先new一个对象
	err := validate.Struct(model)	// 通过对象调用Struct方法
	if err != nil {
		fmt.Println(err)
	}
}

打印错误信息,可以发现其中包含了 不符合标准的字段 和 不符合标准的标签(下文将其统称为错误字段、错误标签)

有了这些信息,就方便我们进行自定义参数信息了!但是仅有这些还不够,我们需要将这些信息各自提取到变量中。

将错误字段和错误标签提取出来

validator包里也给我们提供了方法:我们先将得到的err断言成validator.ValidationErrors,其本质是一个结构体切片,结构体中包含了错误字段和错误标签。接着我们遍历该结构体,即可拿到错误字段和错误标签。

go 复制代码
		// 将err中包含的字段和标签提取出来
		if validationErrors, ok := err.(validator.ValidationErrors); ok {	// 将err断言
			for _, vErr := range validationErrors { // validationErrors 是一个结构体切片
				fmt.Println(vErr.StructField(), vErr.Tag())	// 打印得到的错误字段和错误标签
			}
		}

实战如下

go 复制代码
package main

import (
	"fmt"
	"github.com/go-playground/validator/v10"
)

type RegisterModel struct {
	Username string `validate:"required,numeric"`               // numeric 必须是数字
	Password string `validate:"required,alphanum"`              // alphanum 必须是数字字母组合
	Name     string `validate:"required"`                       // required 必须非空
	Age      int    `validate:"required,gte=0,lte=100,numeric"` // gte, lte 为最大最小值
	Gender   string `validate:"required,oneof=男 女"`             // oneof 必须为其中的某个值
}

func main() {
	// 模拟客户端发来的请求参数
	model := RegisterModel{
		Username: "中文中文",
		Password: "123哈哈哈",
		Name:     "",
	}

	// 用validator包进行校验

	validate := validator.New()

	err := validate.Struct(model)
	if err != nil {
		fmt.Println(err)
		// 将err中包含的字段和标签提取出来
		if validationErrors, ok := err.(validator.ValidationErrors); ok {
			for _, vErr := range validationErrors { // validationErrors 是一个结构体切片
				vErr.StructField()
				vErr.Tag()
				fmt.Println(vErr.StructField(), vErr.Tag())
			}
		}
	}
}

现在我们有了错误字段和错误标签,我们就可以自定义参数错误信息了。

自定义参数错误信息

这里我用的方法是我自创的,比较土,主要是在map中通过错误字段、错误标签映射到自定义的信息。

首先声明两个map

然后在遍历中通过map的映射关系获取到自定义信息。

实战:

go 复制代码
package main

import (
	"fmt"
	"github.com/go-playground/validator/v10"
)

type RegisterModel struct {
	Username string `validate:"required,numeric"`               // numeric 必须是数字
	Password string `validate:"required,alphanum"`              // alphanum 必须是数字字母组合
	Name     string `validate:"required"`                       // required 必须非空
	Age      int    `validate:"required,gte=0,lte=100,numeric"` // gte, lte 为最大最小值
	Gender   string `validate:"required,oneof=男 女"`             // oneof 必须为其中的某个值
}

// 错误标签map
var tagMsg = map[string]string{
	"no-whitespace": "不能含有空格", // 键为结构体标签,值为自定义的错误信息
	"required":      "不能为空",
	"numeric":       "必须是数字",
	"alphanum":      "只能包含字母和数字",
	"oneof":         "错误",
	"lte":           "超出限定范围",
	"gte":           "超出限定范围",
}

// 错误字段map
var fieldMsg = map[string]string{
	"Username":   "账号", // 键为字段名,值为自定义的字段名信息
	"Password":   "密码",
	"Name":       "姓名",
	"Age":        "年龄",
	"Gender":     "性别",
	"Permission": "权限",
}

func main() {
	// 模拟客户端发来的请求参数
	model := RegisterModel{
		Username: "中文中文",
		Password: "123哈哈哈",
		Name:     "",
	}

	// 用validator包进行校验

	validate := validator.New()

	err := validate.Struct(model)
	if err != nil {
		fmt.Println(err)
		// 将err中包含的字段和标签提取出来
		if validationErrors, ok := err.(validator.ValidationErrors); ok {
			for _, vErr := range validationErrors { // validationErrors 是一个结构体切片
				fmt.Println(fieldMsg[vErr.StructField()] + tagMsg[vErr.Tag()])
			}
		}
	}
}

输出结果:

至此,我们就用validator包实现自定义参数错误信息。

感谢浏览,如有不对欢迎指出。

相关推荐
郑州光合科技余经理2 小时前
同城外卖小程序开发:下单成功后,后台导出能不能对上用户端状态
开发语言·前端·git·后端·uni-app·php·ai编程
IT_陈寒2 小时前
Vue的响应式让我熬到凌晨三点,原来漏了这个小细节
前端·人工智能·后端
颜进强3 小时前
01 · NestJS 是什么:用途、解决什么问题、与热门框架对比
前端·后端·ai编程
isfox3 小时前
MapReduce Shuffle 深度解析:数据从 Map 到 Reduce 的完整旅程
后端
颜进强3 小时前
04 · NestJS 依赖注入:你在 `@Module` 写的 providers,和构造参数里那个类型,是怎么"对上"的?
前端·后端·ai编程
谁在黄金彼岸3 小时前
Ollama-使用速查
后端
ServBay3 小时前
Jev是什么?哑巴模型居然全网爆火
后端·aigc·ai编程
烈风逍遥4 小时前
第六篇:RAG 知识库构建与检索全链路
前端·人工智能·后端
花椒技术4 小时前
Agent 沙箱怎么接入生产?花椒的选型、持久化与执行协议实践
人工智能·后端·agent
独泪了无痕4 小时前
Hutool之ArrayUtil:解锁数组操作的新境界
后端