模型绑定和验证

数据绑定及验证概述

要将请求体绑定到结构体中,使用模型绑定。 Gin目前支持JSON、XML、YAML和标准表单值的绑定(foo=bar&boo=baz)。

Gin使用 go-playground/validator/v10 进行验证。 查看标签用法的全部文档。

使用时,需要在要绑定的所有字段上,设置相应的tag。 例如,使用 JSON 绑定时,设置字段标签为 json:"fieldname"。

Gin 的两类绑定方法

Must bindMethods - Bind, BindJSON, BindXML, BindQuery, BindYAML

这些方法属于 MustBindWith 的具体调用。 如果发生绑定错误,则请求终止,并触发 c.AbortWithError(400, err).SetType(ErrorTypeBind)。

Should bindMethods - ShouldBind, ShouldBindJSON, ShouldBindXML, ShouldBindQuery, ShouldBindYAML

这些方法属于 ShouldBindWith 的具体调用。 如果发生绑定错误,Gin 会返回错误并由开发者处理错误和请求。

使用 Bind 方法时,Gin 会尝试根据 Content-Type 推断如何绑定。 如果你明确知道要绑定什么,可以使用 MustBindWith 或 ShouldBindWith。

你也可以指定必须绑定的字段。 如果一个字段的 tag 加上了 binding:"required",但绑定时是空值, Gin 会报错。

数据验证

手册地址 :   https://pkg.go.dev/gopkg.in/go-playground/validator.v10

使用演示

1. 安装 validator 包

go get github.com/go-playground/validator/v10

2. 在代码中引入工具包并使用

2.1 前端数据提交模板代码

<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
    <form action="/" method="post">
        <table width="500">
            <tr>
                <td>姓名</td>
                <td><input type="text" name="Name" /></td>
            </tr>
            <tr>
                <td>年龄</td>
                <td><input type="text" name="Age" /></td>
            </tr>
            <tr>
                <td>手机号</td>
                <td><input type="text" name="Phone" /></td>
            </tr>
            <tr>
                <td>邮箱</td>
                <td><input type="text" name="Email" /></td>
            </tr>
            <tr>
                <td></td>
                <td>
                    <button type="submit">提交</button>
                </td>
            </tr>
        </table>
    </form>
</body>
</html>

2.2 后端数据验证演示代码

package main

import (
	"fmt"
	"html/template"
	"regexp"

	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
)

// 创建一个结构体用于接收及验证POST数据
type Person struct {
	Name  string `validate:"min=1,max=10"`
	Age   int    `validate:"lte=100,gte=10"`
	Phone string `validate:"PhoneNumberCheck"`
	Email string `validate:"email"`
}

// 自定义验证函数 演示
func PhoneNumberCheck(fl validator.FieldLevel) bool {
	checkData := fl.Field().String()
	reg := regexp.MustCompile(`^1[0-9]{10,10}$`)
	return reg.MatchString(checkData)
}

func main() {
	// 初始化 Gin 引擎
	r := gin.Default()
	// 提交页面
	r.GET("/", func(ctx *gin.Context) {
		template, err := template.ParseFiles("./templates/index.html")
		if err != nil {
			fmt.Printf("err: %v\n", err)
		}
		template.Execute(ctx.Writer, nil)
	})
	// 提交接收路由
	r.POST("/", func(ctx *gin.Context) {
		formData := &Person{}
		// 表单数据映射
		ctx.Bind(formData)
		fmt.Printf("formData: %v\n", formData)
		// 表单数据校验
		validate := validator.New()
		// 添加自定义规则
		validate.RegisterValidation("PhoneNumberCheck", PhoneNumberCheck)
		err := validate.Struct(formData)
		if err != nil {
			validationErrs := err.(validator.ValidationErrors)
			fmt.Printf("validationErrs: %v\n", validationErrs)
			fieldName := validationErrs[0].Field()
			ctx.JSON(200, gin.H{"errcode": 300001, "data": "字段 " + fieldName + " 数据错误"})
			return
		}
	})
	r.Run(":80")
}

说明

1. 上面代码演示了使用 ctx.Bind() 函数将表单数据映射为结构体;

2. 使用 validate.New() 函数初始化验证对象;

3. 使用 validate.Struct() 来验证结构体;

4. 使用 validate.RegisterValidation() 来添加自定义验证规则,函数定义请参考 :

func PhoneNumberCheck(fl validator.FieldLevel) bool {
	checkData := fl.Field().String()
	reg := regexp.MustCompile(`^1[0-9]{10,10}$`)
	return reg.MatchString(checkData)
}

5. 验证失败后返回错误信息切片,可以从错误数据中获取到字段名称及错误信息。

验证规则

更多规则请查阅官方手册,手册地址 :

https://pkg.go.dev/github.com/go-playground/validator/v10