一架梯子,一头程序猿,仰望星空!
Go Fiber教程 > 内容正文

Go Fiber参数校验


Go Fiber 验证器主要用于表单参数校验。

验证器包

Fiber可以很好地利用验证器包来确保正确验证要存储的数据。

您可以在下面的结构体中找到所包含字段的详细验证描述:

验证示例

package main

import (
    "fmt"
    "log"
    "strings"

    "github.com/go-playground/validator/v10"
    "github.com/gofiber/fiber/v2"
)

type (
    User struct {
        Name string `validate:"required,min=5,max=20"` // 必填字段,最小长度5个字符,最大长度20个字符
        Age  int    `validate:"required,teener"`       // 必填字段,并且客户端需要实现我们的'teener'标签格式,稍后我们将看到
    }

    ErrorResponse struct {
        Error       bool
        FailedField string
        Tag         string
        Value       interface{}
    }

    XValidator struct {
        validator *validator.Validate
    }

    GlobalErrorHandlerResp struct {
        Success bool   `json:"success"`
        Message string `json:"message"`
    }
)

// 这是验证器实例
// 更多信息请参见:https://github.com/go-playground/validator
var validate = validator.New()

func (v XValidator) Validate(data interface{}) []ErrorResponse {
    validationErrors := []ErrorResponse{}

    errs := validate.Struct(data)
    if errs != nil {
        for _, err := range errs.(validator.ValidationErrors) {
            // 在这种情况下,数据对象实际上保存了User结构体
            var elem ErrorResponse

            elem.FailedField = err.Field() // 导出结构体字段名
            elem.Tag = err.Tag()           // 导出结构体标签
            elem.Value = err.Value()       // 导出字段值
            elem.Error = true

            validationErrors = append(validationErrors, elem)
        }
    }

    return validationErrors
}

func main() {
    myValidator := &XValidator{
        validator: validate,
    }

    app := fiber.New(fiber.Config{
        // 全局自定义错误处理程序
        ErrorHandler: func(c *fiber.Ctx, err error) error {
            return c.Status(fiber.StatusBadRequest).JSON(GlobalErrorHandlerResp{
                Success: false,
                Message: err.Error(),
            })
        },
    })

    // 自定义结构体验证标签格式
    myValidator.validator.RegisterValidation("teener", func(fl validator.FieldLevel) bool {
        // User.Age 需要符合我们的需求,12-18岁。
        return fl.Field().Int() >= 12 && fl.Field().Int() <= 18
    })

    app.Get("/", func(c *fiber.Ctx) error {
        // Create an instance of User
        var user User

        // Bind request data to User struct
        if err := c.QueryParser(&user); err != nil {
            return err
        }

        // Validate User struct
        validationErrors := myValidator.Validate(user)
        if len(validationErrors) > 0 {
            errMsgs := make([]string, 0)

            for _, err := range validationErrors {
                errMsgs = append(errMsgs, fmt.Sprintf(
                    "[%s]: '%v' | 需要实现 '%s'",
                    err.FailedField,
                    err.Value,
                    err.Tag,
                ))
            }

            return &fiber.Error{
                Code:    fiber.ErrBadRequest.Code,
                Message: strings.Join(errMsgs, " and "),
            }
        }

        // Logic, validated with success
        return c.SendString("Hello, World!")
    })

    log.Fatal(app.Listen(":3000"))
}

/**
输出

[1]
请求:

GET http://127.0.0.1:3000/

响应:

{"success":false,"message":"[Name]: '' | 需要实现 'required' 和 [Age]: '0' | 需要实现 'required'"}

[2]
请求:

GET http://127.0.0.1:3000/?name=efdal&age=9

响应:
{"success":false,"message":"[Age]: '9' | 需要实现 'teener'"}

[3]
请求:

GET http://127.0.0.1:3000/?name=efdal&age=

响应:
{"success":false,"message":"[Age]: '0' | 需要实现 'required'"}

[4]
请求:

GET http://127.0.0.1:3000/?name=efdal&age=18

响应:
Hello, World!

**/