Golang 之结构体数据校验

792 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

场景需求

在做数据采集的时候,我们经常需要校验传入的的数据是否合法。

在这种场景下,你如果还在写if else 做判断显然是不合格的,那么如何快速实现数据的校验呢?

js方案

如果是前端的话,一般会使用 validate.js

npm install --save validate.js
var validate = require("validate.js");

java方案

java 也可以使用注解快速实现字段的校验

## 添加依赖
<dependency>
   <groupId>org.springframework.boot</group>
   <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

##注解对象
public class OrderDetailsReqVo {
    @NotBlank // 此注解表明字段不能为null,也不能为空字符串
    private String token;
    @NotBlank // 此注解表明字段不能为null,也不能为空字符串
    private String orderCode;
    // get set......
}

golang方案

golang作为后起之秀,当然不会缺少数据校验的优秀类库,golang不但有,而且更好用,废话不多先上代码:

# 安装类库
$ go get github.com/go-playground/validator/v10
# 编写测试类
import (
	"encoding/json"
	"testing"

	validator "github.com/go-playground/validator/v10"
)
# 定义结构体
type RegistData struct {
	Username string `json:"username" validate:"required"`
	Password string `json:"password" validate:"required"`
	Code     string `json:"code" validate:"required"`
	Email    string `json:"email" validate:"required,email"`
}
# 测试方法
func TestValidate(t *testing.T) {
	validate := validator.New() 
	reg := RegistData{}
	js := "{\"username\":\"1\",\"email\":\"123\"}"
	json.Unmarshal([]byte(js), &reg)
	err := validate.Struct(reg)
	t.Error(err)
}

下面是执行结果

Jietu20220223-114535.jpg

上面的输出结果校验了非空字段,校验了email格式,是不是很方便

只是非空判断显然是不够的,validate还可以做的更多

excludesall:不包含参数中任意的 UNICODE 字符,例如excludesall=ab;
excludesrune:不包含参数表示的 rune 字符,excludesrune=asong;
startswith:以参数子串为前缀,例如startswith=hi;
endswith:以参数子串为后缀,例如endswith=bye。
contains=:包含参数子串,例如contains=email;
containsany:包含参数中任意的 UNICODE 字符,例如containsany=ab;
containsrune:包含参数表示的 rune 字符,例如`containsrune=asong;
excludes:不包含参数子串,例如excludes=email;

ne:不等于参数值,例如ne=5;
gt:大于参数值,例如gt=5;
gte:大于等于参数值,例如gte=50;
lt:小于参数值,例如lt=50;
lte:小于等于参数值,例如lte=50;
oneof:只能是列举出的值其中一个,这些值必须是数值或字符串,以空格分隔,如果字符串中有空格,将字符串用单引号包围,例如oneof=male female。
eq:等于参数值,注意与len不同。对于字符串,eq约束字符串本身的值,而len约束字符串长度。例如eq=10;
len:等于参数值,例如len=10;
max:小于等于参数值,例如max=10;
min:大于等于参数值,例如min=10

email:使用email来限制字段必须是邮件形式,直接写eamil即可,无需加任何指定。
omitempty:字段未设置,则忽略
-:跳过该字段,不检验;
|:使用多个约束,只需要满足其中一个,例如rgb|rgba;
required:字段必须设置,不能为默认值;

上面只是简单列举,详细文档参考Gitee - validator

支持中文

返回英文的错误信息显然是太不友好了,golang validator 可以非常方便的支持国际化,嗯,代码如下

import (
	"encoding/json"
	"testing"

	validator "github.com/go-playground/validator/v10"
)
# 定义结构体
type RegistData struct {
	Username string `json:"username" validate:"required"`
	Password string `json:"password" validate:"required"`
	Code     string `json:"code" validate:"required"`
	Email    string `json:"email" validate:"required,email"`
}
func TestValidateZh(t *testing.T) {
	validate := validator.New()
	//验证
	zh_ch := zh.New()
	uni := ut.New(zh_ch)
	trans, _ := uni.GetTranslator("zh")
	//验证器注册翻译器
	zh_translations.RegisterDefaultTranslations(validate, trans)
	reg := model.RegistData{}
	js := "{\"username\":\"1\",\"email\":\"123\"}"
	json.Unmarshal([]byte(js), &reg)
	err := validate.Struct(reg)
	if err != nil {
		for _, err := range err.(validator.ValidationErrors) {
			t.Errorf(err.Translate(trans))
		}
		return
	}
}

执行输出如下:

Jietu20220223-115846.jpg


开源库真是程序员的宝库啊,请大家且用且珍惜!