18、Go Gin框架中的binding验证器使用

一、binding功能介绍

Gin的binding包提供了一组功能,用于将请求的数据自动绑定到结构体,并根据结构体标签进行数据验证。常用的标签有bindingvalidate,通过这些标签可以指定数据的类型和验证规则。

常见标签

  • binding:"required":表示该字段为必填项

  • binding:"-":忽略该字段,不进行绑定

  • validate:"max=10":表示该字段的值不能超过10

  • validate:"min=1":表示该字段的值不能小于1

  • validate:"email":表示该字段必须是合法的邮箱格式

结构体定义示例

type User struct {
	Name  string `json:"name" binding:"required" validate:"min=3,max=20"`
	Email string `json:"email" binding:"required" validate:"email"`
	Age   int    `json:"age" binding:"required" validate:"min=1,max=100"`
}

在上述示例中,我们定义了一个User结构体,并为每个字段添加了binding和validate标签,指定了各字段的绑定和验证规则。

二、Gin中使用binding和验证器

图片

1. 安装Gin和validator

首先,我们需要安装Gin框架和validator库,可以使用以下命令进行安装:

go get -u github.com/gin-gonic/gin
go get -u github.com/go-playground/validator/v10

go-playground/validator是一个用于 Go 语言的结构体和字段验证包。它具有以下特点:

  • 支持跨字段和跨结构体验证

  • 支持自定义验证器

  • 提供丰富的验证约束

  • 易于使用

以下是该包的一些常见用途:

  • 验证 API 请求参数

  • 验证表单数据

  • 验证数据库模型

2. 绑定数据并验证

在Gin中,我们可以通过ShouldBindShouldBindJSON方法将请求的数据绑定到结构体,并进行验证。下面是一个具体的示例:

package main

import (
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"net/http"
)

// User 结构体
type User struct {
	Name  string `json:"name" binding:"required" validate:"min=3,max=20"`
	Email string `json:"email" binding:"required" validate:"email"`
	Age   int    `json:"age" binding:"required" validate:"min=1,max=100"`
}

// CustomValidator 自定义验证器
type CustomValidator struct {
	validate *validator.Validate
}

// ValidateStruct 验证结构体
func (cv *CustomValidator) ValidateStruct(obj interface{}) error {
	if err := cv.validate.Struct(obj); err != nil {
		return err
	}
	return nil
}

// Main 函数
func main() {
	r := gin.Default()
	//中间件实现验证器验证
	r.Use(func(c *gin.Context) {
		cv := &CustomValidator{validate: validator.New()}
		c.Set("validator", cv)
	})

	//{"name":"shiph","email":"123@qq.com","age":31}
	r.POST("/user", func(c *gin.Context) {
		var user User
		if err := c.ShouldBind(&user); err != nil { //绑定
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}

		if v, ok := c.MustGet("validator").(*CustomValidator); ok { //校验
			if err := v.ValidateStruct(&user); err != nil {
				c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
				return
			}
		}
		c.JSON(http.StatusOK, gin.H{"message": "用户创建成功!", "user": user})
	})

	r.Run()
}

3. 自定义验证器

有时,内置的验证器无法满足我们的需求,我们可以定义自己的验证器。例如,我们希望验证用户名不能包含特殊字符,可以通过自定义验证器实现:

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"net/http"
	"strings"
	"unicode"
)

// User 结构体
type User struct {
	Name  string `json:"name" binding:"required" validate:"min=3,max=20"`
	Email string `json:"email" binding:"required" validate:"email"`
	Age   int    `json:"age" binding:"required" validate:"min=1,max=100"`
}

func isValidUsername(fl validator.FieldLevel) bool {
	username := fl.Field().String()
	for _, char := range username {
		if !unicode.IsLetter(char) && !unicode.IsDigit(char) {
			return false
		}
	}
	return true
}


func main() {
	r := gin.Default()
	validate := validator.New()
	//通过validate.RegisterValidation方法注册了一个自定义验证器isValidUsername,用于验证用户名是否包含特殊字符
	validate.RegisterValidation("username", isValidUsername)

	r.POST("/user", func(c *gin.Context) {
		var user User
		if err := c.ShouldBind(&user); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}

		if err := validate.Struct(user); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}

		c.JSON(http.StatusOK, gin.H{"message": "创建用户成功!", "user": user})
	})

	r.Run()
}

在上述示例中,我们通过validate.RegisterValidation方法注册了一个自定义验证器isValidUsername,用于验证用户名是否包含特殊字符。

四、错误处理

在实际开发中,数据验证错误需要及时反馈给客户端。Gin的binding验证器会在数据验证失败时返回详细的错误信息,我们可以根据这些错误信息进行处理:

func handleError(err error) string {
	if errs, ok := err.(validator.ValidationErrors); ok {
		var errMsgs []string
		for _, e := range errs {
			errMsgs = append(errMsgs, fmt.Sprintf("Field: %s, Error: %s", e.Field(), e.Tag()))
		}
		return strings.Join(errMsgs, ", ")
	}
	return err.Error()
}

通过上述handleError函数,我们可以将验证错误格式化为易于阅读的错误信息。

五、总结

Gin框架中的binding验证器为我们提供了简便的数据绑定和验证功能,通过合理使用binding和validate标签,我们可以确保API接口的数据合法性和完整性。此外,结合自定义验证器和错误处理机制,可以进一步提高数据验证的灵活性和用户体验。

相关推荐

  1. C++11lambda、包装(function、bind

    2024-06-08 03:38:02       12 阅读
  2. C++11std::bind简单使用

    2024-06-08 03:38:02       10 阅读
  3. C++11std::function和std::bind

    2024-06-08 03:38:02       11 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-08 03:38:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-08 03:38:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-08 03:38:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-08 03:38:02       20 阅读

热门阅读

  1. Apache Doris 基础 -- 数据表设计(使用AUTO_INCREMENT)

    2024-06-08 03:38:02       10 阅读
  2. Git 保留空文件夹结构

    2024-06-08 03:38:02       9 阅读
  3. Flink Rest Basic Auth - 安全认证

    2024-06-08 03:38:02       11 阅读
  4. 安卓手机APP开发___设备管理概述

    2024-06-08 03:38:02       10 阅读
  5. Gnu/Linux 系统编程 - 如何获取帮助及一个演示

    2024-06-08 03:38:02       9 阅读
  6. C#朗读语音

    2024-06-08 03:38:02       8 阅读
  7. 第3章 列表简介

    2024-06-08 03:38:02       12 阅读
  8. MySQL数据库(7)

    2024-06-08 03:38:02       10 阅读
  9. 快慢指针算法举例

    2024-06-08 03:38:02       7 阅读