内置的验证规则不能满足所有需求,Gin 允许你注册自定义验证器。
使用 binding.Validator 注册自定义验证函数:
package main
import (
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
"net/http"
"regexp"
)
func main() {
r := gin.Default()
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterValidation("phone", validatePhone)
v.RegisterValidation("username", validateUsername)
}
r.POST("/users", createUser)
r.Run(":8080")
}
func validatePhone(fl validator.FieldLevel) bool {
phone := fl.Field().String()
matched, _ := regexp.MatchString(`^1[3-9]\d{9}$`, phone)
return matched
}
func validateUsername(fl validator.FieldLevel) bool {
username := fl.Field().String()
matched, _ := regexp.MatchString(`^[a-zA-Z][a-zA-Z0-9_]{2,19}$`, username)
return matched
}
type CreateUserRequest struct {
Username string `json:"username" binding:"required,username"`
Phone string `json:"phone" binding:"required,phone"`
}
func createUser(c *gin.Context) {
var req CreateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"username": req.Username,
"phone": req.Phone,
})
}
func validatePhone(fl validator.FieldLevel) bool {
phone := fl.Field().String()
matched, _ := regexp.MatchString(`^1[3-9]\d{9}$`, phone)
return matched
}
使用:
type User struct {
Phone string `binding:"required,phone"`
}
func validateUsername(fl validator.FieldLevel) bool {
username := fl.Field().String()
matched, _ := regexp.MatchString(`^[a-zA-Z][a-zA-Z0-9_]{2,19}$`, username)
return matched
}
import "time"
func validateDate(fl validator.FieldLevel) bool {
date := fl.Field().String()
_, err := time.Parse("2006-01-02", date)
return err == nil
}
使用:
type Event struct {
Date string `binding:"required,date"`
}
func validateStatus(fl validator.FieldLevel) bool {
status := fl.Field().String()
validStatuses := map[string]bool{
"pending": true,
"approved": true,
"rejected": true,
}
return validStatuses[status]
}
func validateMinAge(fl validator.FieldLevel) bool {
param := fl.Param()
minAge, _ := strconv.Atoi(param)
age := fl.Field().Int()
return age >= int64(minAge)
}
v.RegisterValidation("minage", validateMinAge)
使用:
type User struct {
Age int `binding:"required,minage=18"`
}
func validatePasswordConfirm(fl validator.FieldLevel) bool {
password := fl.Field().String()
confirmPassword := fl.Parent().FieldByName("ConfirmPassword").String()
return password == confirmPassword
}
v.RegisterValidation("pwdconfirm", validatePasswordConfirm)
使用:
type RegisterRequest struct {
Password string `binding:"required,min=6"`
ConfirmPassword string `binding:"required"`
}
package main
import (
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
"net/http"
"regexp"
"time"
)
type RegisterRequest struct {
Username string `json:"username" binding:"required,username"`
Email string `json:"email" binding:"required,email"`
Phone string `json:"phone" binding:"required,phone"`
Password string `json:"password" binding:"required,min=6"`
Birthday string `json:"birthday" binding:"required,date"`
}
func main() {
r := gin.Default()
registerValidators()
r.POST("/register", register)
r.Run(":8080")
}
func registerValidators() {
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterValidation("username", validateUsername)
v.RegisterValidation("phone", validatePhone)
v.RegisterValidation("date", validateDate)
}
}
func validateUsername(fl validator.FieldLevel) bool {
username := fl.Field().String()
matched, _ := regexp.MatchString(`^[a-zA-Z][a-zA-Z0-9_]{2,19}$`, username)
return matched
}
func validatePhone(fl validator.FieldLevel) bool {
phone := fl.Field().String()
matched, _ := regexp.MatchString(`^1[3-9]\d{9}$`, phone)
return matched
}
func validateDate(fl validator.FieldLevel) bool {
date := fl.Field().String()
_, err := time.Parse("2006-01-02", date)
return err == nil
}
func register(c *gin.Context) {
var req RegisterRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, gin.H{
"message": "注册成功",
"username": req.Username,
})
}
这一章学习了: