结构体验证
用gin框架的数据验证,可以不用解析数据,减少if else,会简洁许多。
package main
import (
"fmt"
"time"
"github.com/gin-gonic/gin"
)
// person
type Person struct {
//不能位空并且大于10
Age int `form:"age" binding:"required,gt=10"`
Name string `form:"name" binding:"required"`
Brithday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"`
}
func main() {
r := gin.Default()
r.GET("/yangchao", func(ctx *gin.Context) {
var person Person
if err := ctx.ShouldBind(&person); err != nil {
ctx.String(500, fmt.Sprint(err))
return
}
ctx.String(200, fmt.Sprintf("#v", person))
})
r.Run()
}
不带参数访问
携带满足要求的参数
携带不满足要求参数
自定义验证
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
//"gopkg.in/go-playground/validator.v9"
)
/*
对绑定的解析到结构体上的参数,自定义验证功能
对url的接收参数进行判断,判断用户名是否为root,如果是root通过否则返回false
*/
type Login struct {
User string `uri:"user" validate:"CheckName"`
Password string `uri:"password"`
}
//自定义验证函数
func CheckName(fl validator.FieldLevel) bool {
if fl.Field().String() != "root" {
return false
}
return true
}
func main() {
r := gin.Default()
validate := validator.New()
r.GET("/:user/:password", func(ctx *gin.Context) {
var login Login
//注册自定义函数,与struct tag关联
err := validate.RegisterValidation("ChecName", CheckName)
if err := ctx.ShouldBindUri(&login); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
err = validate.Struct(login)
if err != nil {
for _, err := range err.(validator.ValidationErrors) {
fmt.Println(err)
}
return
}
fmt.Println("success")
})
r.Run()
}
package main
import (
"net/http"
"reflect"
"time"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
)
// Booking 包含了绑定和验证数据
type Booking struct {
//定义一个预约时间大于今天的时间
CheckIn time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`
//gtfield=Checkin退出时间大于预约的时间
CheckOut time.Time `form:"check_out" binding:"required,grfield=CheckIn" time_format:"2006-01-02"`
}
func bookableDate(
v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,
field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,
) bool {
//field.Interface().(time.Time)获取参数值并且转换为时间格式
if date, ok := field.Interface().(time.Time); ok {
today := time.Now()
if today.Unix() > date.Unix() {
return false
}
}
return true
}
func GetBookable(ctx *gin.Context) {
var b Booking
if err := ctx.ShouldBindWith(&b, binding.Query); err == nil {
ctx.JSON(http.StatusOK, gin.H{
"message": "Booking dates are valid!",
})
} else {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
}
func main() {
route := gin.Default()
//注册验证
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
//绑定第一个参数是验证的函数第二个参数是自定义的验证函数
v.RegisterValidation("bookabledate", bookableDate)
}
route.GET("/yangchao", GetBookable)
route.Run()
}
自定义验证说明
Validator 是基于 tag(标记)实现结构体和单个字段的值验证库,它包含以下功能:
- 使用验证 tag(标记)或自定义验证器进行跨字段和跨结构体验证。
- 关于 slice、数组和 map,允许验证多维字段的任何或所有级别。
- 能够深入 map 键和值进行验证。
- 通过在验证之前确定接口的基础类型来处理类型接口。
- 处理自定义字段类型(如 sql 驱动程序 Valuer)。
- 别名验证标记,它允许将多个验证映射到单个标记,以便更轻松地定义结构体上的验证。
- 提取自定义的字段名称,例如,可以指定在验证时提取 JSON 名称,并在生成的 FieldError 中使用该名称。
- 可自定义 i18n 错误消息。
- Web 框架 gin 的默认验证器。
以下是常用的标签
标签 | 描述 |
eq | 等于 |
gt | 大于 |
gte | 大于等于 |
lt | 小于 |
lte | 小于等于 |
ne | 不等于 |
max | 最大值 |
min | 最小值 |
oneof | 其中一个 |
required | 必需的 |
unique | 唯一的 |
isDefault | 默认值 |
len | 长度 |
email | 邮箱格式 |
日志文件
package main
import (
"io"
"os"
"github.com/gin-gonic/gin"
)
func main() {
gin.DisableConsoleColor()
// Logging to a file.
f, _ := os.Create("gin.log")
gin.DefaultWriter = io.MultiWriter(f)
// 如果需要同时将日志写入文件和控制台,请使用以下代码。
// gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.String(200, "pong")
})
r.Run()
}