Gin框架表单验证


package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "github.com/gin-gonic/gin/binding"
    "github.com/go-playground/locales/en"
    "github.com/go-playground/locales/zh"
    ut "github.com/go-playground/universal-translator"
    validator "github.com/go-playground/validator/v10"
    en_translations "github.com/go-playground/validator/v10/translations/en"
    zh_translations "github.com/go-playground/validator/v10/translations/zh"
    "net/http"
    "reflect"
    "strings"
)

type LoginForm struct {
    User     string `json:"user" binding:"required,min=3,max=10"`
    Password string `json:"password" binding:"required,min=6,max=20"`
}

type SignUpFrom struct {
    Name       string `json:"name" binding:"required,min=3,max=10"`
    Age        uint8  `json:"age" binding:"required,gte=0,lte=150"`
    Email      string `json:"email" binding:"required,email"`
    Password   string `json:"password" binding:"required,min=6,max=20"`
    RePassword string `json:"re_password" binding:"required,min=6,max=20,eqfield=Password"`
}

var trans ut.Translator

func SignUp(c *gin.Context) {
    var signUpFrom SignUpFrom
    err := c.ShouldBind(&signUpFrom)
    if err != nil {
        errs, ok := err.(validator.ValidationErrors)
        if !ok {
            c.JSON(http.StatusOK, gin.H{
                "error": err.Error(),
            })
        }
        c.JSON(http.StatusBadRequest, gin.H{
            "error": removeTopStruct(errs.Translate(trans)),
        })
    } else {
        c.JSON(http.StatusOK, gin.H{
            "msg": "注册成功!",
        })
    }
}

func Login(c *gin.Context) {
    var loginForm LoginForm
    err := c.ShouldBind(&loginForm)
    if err != nil {
        errs, ok := err.(validator.ValidationErrors)
        if !ok {
            c.JSON(http.StatusOK, gin.H{
                "error": errs.Error(),
            })
        }
        c.JSON(http.StatusBadRequest, gin.H{
            "error": removeTopStruct(errs.Translate(trans)),
        })
    } else {
        c.JSON(http.StatusOK, gin.H{
            "msg": "登陆成功!",
        })
    }
}

func removeTopStruct(fields map[string]string) map[string]string {
    res := make(map[string]string, len(fields))
    for field, err := range fields {
        key := field[strings.Index(field, ".")+1:]
        res[key] = err
    }
    return res
}

func InitTrans(locale string) (err error) {
    if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
        v.RegisterTagNameFunc(func(field reflect.StructField) string {
            name := strings.SplitN(field.Tag.Get("json"), ",", 2)[0]
            if name == "-" {
                return ""
            }
            return name
        })
        // 注册翻译器
        zhT := zh.New()
        enT := en.New()
        uni := ut.New(enT, zhT, enT)
        trans, ok = uni.GetTranslator(locale)
        if !ok {
            return fmt.Errorf("uni.GetTranslator(%s)", locale)
        }
        switch locale {
        case "en":
            err := en_translations.RegisterDefaultTranslations(v, trans)
            if err != nil {
                panic("failed to listen:" + err.Error())
                return err
            }
        case "zh":
            err := zh_translations.RegisterDefaultTranslations(v, trans)
            if err != nil {
                panic("failed to listen:" + err.Error())
                return err
            }
        default:
            err := en_translations.RegisterDefaultTranslations(v, trans)
            if err != nil {
                panic("failed to listen:" + err.Error())
                return err
            }
        }
    }
    return
}

func main() {

    err := InitTrans("zh")
    if err != nil {
        fmt.Println("初始化翻译器失败!")
        return
    } else {
        fmt.Println("初始化翻译器成功!")
    }
    r := gin.Default()
    r.POST("/login", Login)
    r.POST("/signup", SignUp)
    err = r.Run()
    if err != nil {
        panic("failed to listen:" + err.Error())
    }
}