【Golang】validator库的使用

package mainimport ("fmt""github.com/go-playground/validator"
)// MyStruct .. validate:"is-awesome"是一个结构体标签,它告诉验证器使用名为is-awesome的验证规则来验证String字段。
type MyStruct struct {String string `validate:"is-awesome"`
}// use a single instance of Validate, it caches struct info
var validate *validator.Validatefunc main() {validate = validator.New()//注册一个自定义验证函数ValidateMyVal,它将被用来验证标签为is-awesome的字段。validate.RegisterValidation("is-awesome", ValidateMyVal)s := MyStruct{String: "awesome"}err := validate.Struct(s)if err != nil {fmt.Printf("Err(s):%+v\n", err)}s.String = "not awesome"err = validate.Struct(s)if err != nil {fmt.Printf("Err(s):\n%+v\n", err)}
}// ValidateMyVal implements validator.Func
func ValidateMyVal(fl validator.FieldLevel) bool {return fl.Field().String() == "awesome"
}

custom-validation  结果

Err(s):
Key: 'MyStruct.String' Error:Field validation for 'String' failed on the 'is-awesome' tag

示例代码2

custom

package mainimport ("database/sql""database/sql/driver""fmt""reflect""github.com/go-playground/validator/v10"
)// DbBackedUser 用户结构体,由数据库支持
type DbBackedUser struct {Name sql.NullString `validate:"required"` // 可以为NULL的字符串,验证规则为必填Age  sql.NullInt64  `validate:"required"` // 可以为NULL的整数,验证规则为必填
}// 使用单一实例的验证器,它缓存结构体信息
var validate *validator.Validatefunc main() {// 创建一个新的验证器实例validate = validator.New()// 注册所有sql.Null*类型,使用自定义的ValidateValuer函数validate.RegisterCustomTypeFunc(ValidateValuer, sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})// 构建对象进行验证// Name字段为空字符串但Valid为true,表示非NULL;Age字段为0且Valid为false,表示NULLx := DbBackedUser{Name: sql.NullString{String: "", Valid: true}, Age: sql.NullInt64{Int64: 0, Valid: false}}// 对x进行结构体验证err := validate.Struct(x)// 如果验证失败,打印错误信息if err != nil {fmt.Printf("Err(s):\n%+v\n", err)}
}// ValidateValuer实现了validator.CustomTypeFunc接口
func ValidateValuer(field reflect.Value) interface{} {// 如果field实现了driver.Valuer接口if valuer, ok := field.Interface().(driver.Valuer); ok {// 尝试获取valuer的值val, err := valuer.Value()if err == nil {return val // 如果没有错误,返回值}// 如果有错误,可以根据需要处理}return nil // 如果没有实现Valuer接口或有错误,返回nil
}
// Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified.
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
func (v *Validate) Struct(s interface{}) error {return v.StructCtx(context.Background(), s)
}// StructCtx validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified
// and also allows passing of context.Context for contextual validation information.
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
func (v *Validate) StructCtx(ctx context.Context, s interface{}) (err error) {val := reflect.ValueOf(s)top := valif val.Kind() == reflect.Ptr && !val.IsNil() {val = val.Elem()}if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) {return &InvalidValidationError{Type: reflect.TypeOf(s)}}// good to validatevd := v.pool.Get().(*validate)vd.top = topvd.isPartial = false// vd.hasExcludes = false // only need to reset in StructPartial and StructExceptvd.validateStruct(ctx, top, val, val.Type(), vd.ns[0:0], vd.actualNs[0:0], nil)if len(vd.errs) > 0 {err = vd.errsvd.errs = nil}v.pool.Put(vd)return
}
package mainimport ("fmt""github.com/go-playground/validator/v10"
)// Test ...
type Test struct {Array []string          `validate:"required,gt=0,dive,required"`Map   map[string]string `validate:"required,gt=0,dive,keys,keymax,endkeys,required,max=1000"`
}// use a single instance of Validate, it caches struct info
var validate *validator.Validatefunc main() {validate = validator.New()// registering alias so we can see the differences between// map key, value validation errorsvalidate.RegisterAlias("keymax", "max=10")//注册别名规则 max=10var test Testval(test)//空值报错requiredtest.Array = []string{""}//校验第一个字段非空require dive,required test.Map = map[string]string{"test > than 10": ""}//超过了max=10的最大长度 并且第二个值不为空val(test)test.Array = []string{"1"}test.Map = map[string]string{"": "11"}//require针对value而不是keyval(test)
}func val(test Test) {fmt.Println("testing")err := validate.Struct(test)fmt.Println(err)
}

结合正则表达式

package mainimport ("database/sql""fmt""regexp""github.com/go-playground/validator/v10"
)// DbBackedUser 用户结构体,由数据库支持
type DbBackedUser struct {Name sql.NullString `validate:"required,namePattern"` // 可以为NULL的字符串,验证规则为必填和符合名称模式Age  sql.NullInt64  `validate:"required,gt=0"`       // 可以为NULL的整数,验证规则为必填且大于0
}// 使用单一实例的验证器,它缓存结构体信息
var validate *validator.Validatefunc main() {// 创建一个新的验证器实例validate = validator.New()// 注册自定义验证函数validate.RegisterValidation("namePattern", NamePattern)validate.RegisterValidation("gt", GreaterThanZero)// 构建对象进行验证x := DbBackedUser{Name: sql.NullString{String: "JohnDoe", Valid: true}, Age: sql.NullInt64{Int64: 18, Valid: true}}// 对x进行结构体验证err := validate.Struct(x)// 如果验证失败,打印错误信息if err != nil {fmt.Printf("Err(s):\n%+v\n", err)}else{fmt.Println("success")}x = DbBackedUser{Name: sql.NullString{String: "JohnDoe_123", Valid: true}, Age: sql.NullInt64{Int64: 18, Valid: true}}// 对x进行结构体验证err = validate.Struct(x)// 如果验证失败,打印错误信息if err != nil {fmt.Printf("Err(s):\n%+v\n", err)}else{fmt.Println("success")}}// NamePattern 自定义验证函数,检查姓名是否只包含字母
func NamePattern(fl validator.FieldLevel) bool {nullString := fl.Field().Interface().(sql.NullString)if !nullString.Valid {return false}reg := regexp.MustCompile(`^[a-zA-Z]+$`)return reg.MatchString(nullString.String)
}// GreaterThanZero 自定义验证函数,检查数值是否大于0
func GreaterThanZero(fl validator.FieldLevel) bool {nullInt64 := fl.Field().Interface().(sql.NullInt64)if !nullInt64.Valid {return false}return nullInt64.Int64 > 0
}

参考validator/_examples at master · go-playground/validator · GitHub

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux(CentOS)安装 MySQL

CentOS版本:CentOS 7 MySQL版本:MySQL Community Server 8.4.3 LTS 1、下载 MySQL 打开MySQL官网:https://www.mysql.com/ 直接下载网址:https://dev.mysql.com/downloads/mysql/ 其他版本 2、上传 MySQL 文件到 CentOS 使用F…

Pytorch实现transformer语言模型

转载自&#xff1a;| 03_language_model/02_Transformer语言模型.ipynb | 从头训练Transformer语言模型 |Open In Colab | Transformer语言模型 本节训练一个 sequence-to-sequence 模型&#xff0c;使用pytorch的 nn.Transformer <https://pytorch.org/docs/master/nn.ht…

<Project-20 YT-DLP> 给视频网站下载工具 yt-dlp/yt-dlp 加个页面 python web

介绍 yt-dlp Github 项目&#xff1a;https://github.com/yt-dlp/yt-dlp A feature-rich command-line audio/video downloader 一个功能丰富的视频与音频命令行下载器 原因与功能 之前我用的 cobalt 因为它不再提供Client Web功能&#xff0c;只能去它的官网使用。 翻 redd…

Sqli-Labs

目录 解题思路 题目设计原理 总结 解题思路 什么&#xff1f;sqli-labs&#xff1f;让我看看。还真是。想起了当初刚学被支配的恐惧。 悄咪咪点开第一关看看能不能秒了。测试闭合老样子&#xff0c;单引号闭合&#xff0c;双引号等都成功。这里 and 11 和 # 都不能通过检测&…

【基于Zynq FPGA对雷龙SD NAND的测试】

一、SD NAND 特征 1.1 SD 卡简介 雷龙的 SD NAND 有很多型号&#xff0c;在测试中使用的是 CSNP4GCR01-AMW 与 CSNP32GCR01-AOW。芯片是基于 NAND FLASH 和 SD 控制器实现的 SD 卡。具有强大的坏块管理和纠错功能&#xff0c;并且在意外掉电的情况下同样能保证数据的安全。 …

【NOIP提高组】引水入城

【NOIP提高组】引水入城 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 在一个遥远的国度&#xff0c;一侧是风景秀美的湖泊&#xff0c;另一侧则是漫无边际的沙漠。该国的行政 区划十分特殊&#xff0c;刚好构成一个N行M列的矩形&#xff…

鸿蒙开发:arkts 如何读取json数据

为了支持ArkTS语言的开发&#xff0c;华为提供了完善的工具链&#xff0c;包括代码编辑器、编译器、调试器、测试工具等。开发者可以使用这些工具进行ArkTS应用的开发、调试和测试。同时&#xff0c;华为还提供了DevEco Studio这一一站式的开发平台&#xff0c;为运行在Harmony…

OpenCV视觉分析之目标跟踪(11)计算两个图像之间的最佳变换矩阵函数findTransformECC的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 根据 ECC 标准 78找到两幅图像之间的几何变换&#xff08;warp&#xff09;。 该函数根据 ECC 标准 ([78]) 估计最优变换&#xff08;warpMatri…

【2024最新版Kotlin教程】Kotlin第一行代码系列第五课-类继承,抽象类,接口

【2024最新版Kotlin教程】Kotlin第一行代码系列第五课-类继承&#xff0c;抽象类&#xff0c;接口 为什么要有继承呢&#xff0c;现实中也是有继承的&#xff0c;对吧&#xff0c;你继承你爸的遗产&#xff0c;比如你爸建好了一个房子&#xff0c;儿子继承爸&#xff0c;就得了…

iOS用rime且导入自制输入方案

iPhone 16 的 cantonese 只能打传统汉字&#xff0c;没有繁简转换&#xff0c;m d sh d。考虑用「仓」输入法 [1] 使用 Rime 打字&#xff0c;且希望导入自制方案 [2]。 仓输入法有几种导入方案的方法&#xff0c;见 [3]&#xff0c;此处记录 wifi 上传法。准备工作&#xff1…

基于Zynq FPGA的雷龙SD NAND存储芯片性能测试

文章目录 前言一、SD NAND特征1.1 SD卡简介1.2 SD卡Block图 二、SD卡样片三、Zynq测试平台搭建3.1 测试流程3.2 SOC搭建 四、软件搭建五、测试结果六、总结 前言 随着嵌入式系统和物联网设备的快速发展&#xff0c;高效可靠的存储解决方案变得越来越重要。雷龙发展推出的SD NA…

【动态规划 数学】2745. 构造最长的新字符串|1607

本文涉及知识点 C动态规划 数学 LeetCode2745. 构造最长的新字符串 给你三个整数 x &#xff0c;y 和 z 。 这三个整数表示你有 x 个 “AA” 字符串&#xff0c;y 个 “BB” 字符串&#xff0c;和 z 个 “AB” 字符串。你需要选择这些字符串中的部分字符串&#xff08;可以全…

【Linux驱动开发】timer库下的jiffies时间戳和延时驱动编写

【Linux驱动开发】timer库下的jiffies时间戳和延时驱动编写 gitee地址&#xff1a; https://gitee.com/Mike_Zhou_Admin/Linux_Driver_Timestamp_Driver/更新以gitee为准 文章目录 timer库时间戳函数延时函数驱动代码应用测试附录&#xff1a;嵌入式Linux驱动开发基本步骤开发…

了解云计算工作负载保护的重要性及必要性

云计算de小白 云计算技术的快速发展使数据和应用程序安全成为一种关键需求&#xff0c;而不仅仅是一种偏好。随着越来越多的客户公司将业务迁移到云端&#xff0c;保护他们的云工作负载&#xff08;指所有部署的应用程序和服务&#xff09;变得越来越重要。云工作负载保护&…

C语言 循环高级

时间&#xff1a;2024.11.6 一、学习内容 1、无限循环 无限循环&#xff1a;循环永远停不下来 注意点&#xff1a;无限循环因为永远停不下来&#xff0c;所以下面不能再写其他的代码了 2、break 跳转控制语句&#xff1a; 在循环的过程中&#xff0c;跳到其他语句上执行 #…

易语言模拟真人动态生成鼠标滑动路径

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…

CSS学习之Grid网格布局基本概念、容器属性

网格布局 网格布局&#xff08;Grid&#xff09;是将网页划分成一个个网格单元&#xff0c;可任意组合不同的网格&#xff0c;轻松实现各种布局效果&#xff0c;也是目前CSS中最强大布局方案&#xff0c;比Flex更强大。 基本概念 容器和项目 当一个 HTML 元素将 display 属性…

聊一聊Elasticsearch的索引的分片分配机制

1、什么是分片分配 分片分配是由ES主节点将索引分片移动到ES集群中各个节点上的过程。 该过程尽量保证&#xff0c;同一个索引的分片尽量分配到更多的节点上&#xff0c;以此来达到读写索引的时候可以利用更多硬件资源的效果。 在分配过程当中&#xff0c;也不能将某个主分片…

springboot的增删改查商城小实践(b to c)

首先准备一张表&#xff0c;根据业务去设计表 订单编号是参与业务的&#xff0c;他那订单编号里面是有特殊意义的&#xff0c;比如说像什么一些年月日什么的&#xff0c;一些用户的ID都在那编号里面呢&#xff1f;不能拿这种东西当主件啊 根据数据量去决定数据类型 价格需要注意…

Ubuntu 安装 RTL8811cu 网卡驱动

一、支持的网卡 RTL8811AU、RTL8811CU、RTL8821AU、RTL8821CU 二、下载驱动 github&#xff1a;https://github.com/brektrou/rtl8821CU 直接下载zip源码即可 三、安装驱动 sudo su -i #切换到root用户 apt-get update #更新安装源 apt-get install -y dkms …