前言
哈喽,大家好,我是asong。这是我的第十篇原创文章。这周在公司做项目,在做API部分开发时,需要对请求参数的校验,防止用户的恶意请求。例如日期格式,用户年龄,性别等必须是正常的值,不能随意设置。最开始在做这一部分的时候,我采用老方法,自己编写参数检验方法,统一进行参数验证。后来在同事CR的时候,说GIN有更好的参数检验方法,gin框架使用github.com/go-playground/validator进行参数校验,我们只需要在定义结构体时使用binding
或validate
tag标识相关校验规则,就可以进行参数校验了,很方便。相信也有很多小伙伴不知道这个功能,今天就来介绍一下这部分。
快速安装
使用之前,我们先要获取validator
这个库。
# 第一次安装使用如下命令
$ go get github.com/go-playground/validator/v10
# 项目中引入包
import "github.com/go-playground/validator/v10"
简单示例
安装还是很简单的,下面我先来一个官方样例,看看是怎么使用的,然后展开分析。
代码语言:javascript复制package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
type RegisterRequest struct {
Username string `json:"username" binding:"required"`
Nickname string `json:"nickname" binding:"required"`
Email string `json:"email" binding:"required,email"`
Password string `json:"password" binding:"required"`
Age uint8 `json:"age" binding:"gte=1,lte=120"`
}
func main() {
router := gin.Default()
router.POST("register", Register)
router.Run(":9999")
}
func Register(c *gin.Context) {
var r RegisterRequest
err := c.ShouldBindJSON(&r)
if err != nil {
fmt.Println("register failed")
c.JSON(http.StatusOK, gin.H{"msg": err.Error()})
return
}
//验证 存储操作省略.....
fmt.Println("register success")
c.JSON(http.StatusOK, "successful")
}
- 测试
curl --location --request POST 'http://localhost:9999/register'
--header 'Content-Type: application/json'
--data-raw '{
"username": "asong",
"nickname": "golang梦工厂",
"email": "7418.com",
"password": "123",
"age": 140
}'
- 返回结果
{
"msg": "Key: 'RegisterRequest.Email' Error:Field validation for 'Email' failed on the 'email' tagnKey: 'RegisterRequest.Age' Error:Field validation for 'Age' failed on the 'lte' tag"
}
看这个输出结果,我们可以看到validator
的检验生效了,email字段不是一个合法邮箱,age字段超过了最大限制。我们只在结构体中添加tag就解决了这个问题,是不是很方便,下面我们就来学习一下具体使用。
validator库
gin框架是使用validator.v10这个库来进行参数验证的,所以我们先来看看这个库的使用。
先安装这个库:
代码语言:javascript复制$ go get github.com/go-playground/validator/v10
然后先写一个简单的示例:
代码语言:javascript复制package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type User struct {
Username string `validate:"min=6,max=10"`
Age uint8 `validate:"gte=1,lte=10"`
Sex string `validate:"oneof=female male"`
}
func main() {
validate := validator.New()
user1 := User{Username: "asong", Age: 11, Sex: "null"}
err := validate.Struct(user1)
if err != nil {
fmt.Println(err)
}
user2 := User{Username: "asong111", Age: 8, Sex: "male"}
err = validate.Struct(user2)
if err != nil {
fmt.Println(err)
}
}
我们在结构体定义validator标签的tag,使用validator.New()
创建一个验证器,这个验证器可以指定选项、添加自定义约束,然后在调用他的Struct()
方法来验证各种结构对象的字段是否符合定义的约束。
上面的例子,我们在User结构体中,有三个字段:
- Name:通过min和max来进行约束,Name的字符串长度为[6,10]之间。
- Age:通过gte和lte对年轻的范围进行约束,age的大小大于1,小于10。
- Sex:通过oneof对值进行约束,只能是所列举的值,oneof列举出性别为男士