go gin web 应用 实现 参数校验 自定义功能

1.准备工作

在进行 web 业务开发时,尽管 validator/v10 这个库已经为我们预置了很多校验的字段约束,难免有些场景下,我们想自定义一些规则进去,比如校验用户注册的密码,约束是含数字、大写字母、小写字母,特殊字符("*|&|$|#")的至少3种,常规的字段约束此时就不管用了,怎么办,当然可以通过自定义约束字段检验,自己操作的空间就大很多了。

根据 validator 库的相关规则,只要我们实现了如下函数:

// Func accepts a FieldLevel interface for all validation needs. The return
// value should be true when validation succeeds.
type Func func(fl FieldLevel) bool

就可以根据在定义 struct 时的 tag 字段注册到 validator 中。

怎样是不是很简单,接下来我们以简单的用户注册与用户登录的场景来实操下。

2.相关代码

目录结构

业务代码

项目启动

// main.go
package main
import (
"github.com/gin-gonic/gin"
v1 "go-gin-userDefinedValidator/api/v1"
)
func main() {
r := gin.Default()
r.GET("/hello", v1.Hello)
r.POST("/user/add", v1.AddUser)
r.POST("/auth/login", v1.Login)
_ = r.Run(":8080")
}

接口路由函数

// router.go
package v1
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
"go-gin-userDefinedValidator/internal/request"
validate "go-gin-userDefinedValidator/internal/validator"
)
func Hello(ctx *gin.Context) {
ctx.JSON(http.StatusOK, gin.H{
"msg": "hello, this is from gin app server.",
})
}
func AddUser(ctx *gin.Context) {
var err error
var user request.UserParams
err = ctx.ShouldBindBodyWith(&user, binding.JSON)
if err != nil {
ctx.JSON(http.StatusOK, gin.H{
"msg": err.Error(),
})
return
}
err = validate.Validate.Struct(user)
if err != nil {
details := make([]map[string]interface{}, 0)
for _, e := range err.(validator.ValidationErrors) {
m := make(map[string]interface{})
m["field"] = e.Field()
m["value"] = e.Value()
m["tag"] = e.Tag()
details = append(details, m)
}
ctx.JSON(http.StatusOK, gin.H{
"msg": "validate error",
"details": details,
})
return
}
ctx.JSON(http.StatusOK, gin.H{
"msg": fmt.Sprintf("Registered success, welcome user: %s", user.Username),
})
}
func Login(ctx *gin.Context) {
var err error
var login request.LoginParams
err = ctx.ShouldBindBodyWith(&login, binding.JSON)
if err != nil {
ctx.JSON(http.StatusOK, gin.H{
"msg": err.Error(),
})
return
}
err = validate.Validate.Struct(login)
if err != nil {
details := make([]map[string]interface{}, 0)
for _, e := range err.(validator.ValidationErrors) {
m := make(map[string]interface{})
m["field"] = e.Field()
m["value"] = e.Value()
m["tag"] = e.Tag()
details = append(details, m)
}
ctx.JSON(http.StatusOK, gin.H{
"msg": "validate error",
"details": details,
})
return
}
ctx.JSON(http.StatusOK, gin.H{
"msg": fmt.Sprintf("user: %s, login success.", login.Username),
})
}

接口请求参数

// reqParams.go
package request
type UserParams struct {
Username string `json:"username" validate:"required,min=4,max=20"`
Password string `json:"password" validate:"required,passwd"`
ConfirmPassword string `json:"confirmPassword" validate:"required,eqfield=Password"`
Age int `json:"age,omitempty" validate:"omitempty,age"`
Gender int `json:"gender,omitempty" validate:"omitempty,oneof=1 0"`
}
type LoginParams struct {
Username string `json:"username" validate:"required,min=4,max=20"`
Password string `json:"password" validate:"required,passwd"`
}

自定义验证器

// myValidator.go
package validator
import (
"fmt"
"github.com/go-playground/validator/v10"
)
var Validate *validator.Validate
// 初始化注册自定义校验
func init() {
registerMyValidator()
}
func registerMyValidator() {
Validate = validator.New()
err := Validate.RegisterValidation("passwd", passwdFunc)
if err != nil {
fmt.Println("register passwd validator failed.")
return
}
err = Validate.RegisterValidation("age", ageFunc)
if err != nil {
fmt.Println("register age validator failed.")
return
}
fmt.Println("register user defined validator success.")
}
// user defined validator
// 定义密码验证
func passwdFunc(fl validator.FieldLevel) bool {
pwd := fl.Field().String()
if len(pwd) < 8 || len(pwd) > 20 {
return false
}
return true
}
// 定义age验证
func ageFunc(fl validator.FieldLevel) bool {
age := fl.Field().Int()
if age < 18 || age > 100 {
return false
}
return true
}

示例中,我们以简单的密码和年龄校验为例,实现了简单业务,下面看看相关测试。

3.测试

hello 接口

正常注册请求参数

多个字段参数问题

正常登陆

异常登陆

通过本示例的学习,相信你也可以轻松掌握自定义验证器的使用。

参考文章:

posted on   进击的davis  阅读(407)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2021-03-25 django项目实战-基本指南
2021-03-25 django项目使用mysql作为数据库配置
2021-03-25 python logging模块的快速应用-输出到文件
2021-03-25 linux 安装mysql及常用配置 授权 改密 开放端口

导航

< 2025年3月 >
23 24 25 26 27 28 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 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示