企业网站制作的方法,单本小说wordpress,制作海报的app免费,网站多套系统如何调用一. 结构体验证 用gin框架的数据验证#xff0c;可以不用解析数据#xff0c;减少if else。如下面的代码#xff0c;如果需要增加判断条件#xff0c;就需要增加if或者if else。
type MyApi struct {a intb string
}func checkMyApi(val *MyApi) bool {if val.a 0 {retur…一. 结构体验证 用gin框架的数据验证可以不用解析数据减少if else。如下面的代码如果需要增加判断条件就需要增加if或者if else。
type MyApi struct {a intb string
}func checkMyApi(val *MyApi) bool {if val.a 0 {return false}if val.b ! foo val.b ! bar {return false}return true
} 1.1 binding标签 在 Go 语言中结构体的binding标签用于指定结构体字段在进行数据绑定如表单数据绑定或请求体绑定时的规则和验证。用于gin验证器。
package mainimport (fmtnet/httpgithub.com/gin-gonic/gin
)type MyApi struct {A int form:a binding:requiredB string form:b binding:required,oneoffoo barC []float64 form:c binding:required,gt0
}func main() {r : gin.Default()r.GET(/check, func(c *gin.Context) {var api MyApiif err : c.ShouldBind(api); err ! nil {c.String(http.StatusBadRequest, err.Error())return}str : fmt.Sprintf(a:%d, b:%s, c:%#v, api.A, api.B, api.C)c.String(http.StatusOK, str)})r.Run()
} required表示字段不能为对应类型的零值。 oneof用于限制字段取值必须是指定的多个值中的一个多个值之间使用空格分隔。如果字符串本身包含空格可以使用单引号括起来。 gt表示greater than大于。对于数字这将确保值大于给定的值。对于字符串它检查字符串长度是否大于给定值。对于切片数组和映射验证元素的数量。 常用tag
required表示该字段是必需的不能为空。
min指定字段的最小值。
max指定字段的最大值。
eq: 等于如binding:“eq3”
ne: 不等于如binding:“ne12”
gt: 大于
gte: 大于等于
lt: 小于
lte: 小于等于
eqfield: 等于其它字段如; Password string bingding:“eqfieldConfirmPassword” 表示密码和确认密码一致
nefield: 不等于其它字段
email验证字段是否为有效的电子邮件地址。如binding:“email”
url验证字段是否为有效的 URL。如binding:“url”
datetime验证字段是否为有效的日期时间格式。
len指定字段的长度。
default指定字段的默认值。
omitempty指定当字段为空时绑定时忽略该字段。
oneof:枚举验证如binding:“oneofman woman”, 只能为man或者woman
contains: 字符串验证包含某字符串如binding:“containslove”
excludes: 字符串验证不包含某字符串, 如binding:“containsmoney”
startswith 字符串验证字符串前缀
endswith:字符串验证字符串后缀
pattern使用正则表达式验证字段的值。
datetime: 日期格式验证如binding:“datetime2006-01-02 15:04:05”,注时间必须是2006年1月2号下午3点4分5秒不可以修改年月日时分秒的值。
忽略字段binding:“-” 1.2 dive的使用 先看一个实例的请求结构体
type PostAttributeValuesReq struct {CreatorId string binding:required // 创建者IDValues []struct {Value string binding:required // 属性值Days uint // 天数计费模式使用} binding:required,gt0 // 属性值数组
}假设使用json传参发现Values.Value字段没有识别出来也就是说切片元素struct字段的required并没有生效。
{creatorId:dablelv,values:[{}]
}可以使用dive标签这是告诉验证器深入到切片数组或映射中并使用元素标签来验证切片数组或映射元素。
type PostAttributeValuesReq struct {CreatorId string binding:required // 创建者IDValues []struct {Value string binding:required // 属性值Days uint // 天数计费模式使用} binding:required,gt0,dive // 属性值数组
}1.3 validate标签 validate用于数据验证库的字段验证。
package mainimport (fmtnet/httpgithub.com/gin-gonic/gingithub.com/go-playground/validator/v10
)type MyApi struct {A int form:a validate:requiredB string form:b validate:required,oneoffoo barC []float64 form:c validate:required,gt0
}func main() {r : gin.Default()r.GET(/check, func(c *gin.Context) {var api MyApiif err : c.ShouldBind(api); err ! nil {c.String(http.StatusBadRequest, err.Error())return}//数据验证validate : validator.New()if err : validate.Struct(api); err ! nil {c.String(http.StatusBadRequest, err.Error())return}str : fmt.Sprintf(a:%d, b:%s, c:%#v, api.A, api.B, api.C)c.String(http.StatusOK, str)})r.Run()
} validate的常用taghttps://github.com/go-playground/validator/blob/master/README.md 1.4 binding和validate区别 上下文
binding主要用于Web框架的参数绑定例如Gin。在请求参数绑定到结构体字段时验证数据。validate主要用于数据验证库例如go-playground/validator。 错误处理
在Web框架中binding通常会导致框架返回HTTP 400 Bad Request错误指示客户端请求参数不合法。在数据验证库中会在验证时产生相应的验证错误开发者可根据需要进行特别处理。 使用场景
适用于Web框架的参数绑定适用于在通用的数据验证场景中
二. 自定义验证 使用go-playground/validator包。 2.1 validator包简介 validator包是Golang中一个非常受欢迎的数据验证工具它提供了丰富的验证规则和简单易用的API。使用validator包可以轻松的定义和执行各种验证规则如必填字段最大长度最小值等。同时validator包还支持自定义验证规则可根据具体业务需求进行扩展。 validator包安装
go get github.com/go-playground/validator/v10 2.2 基本使用 2.3 自定义规则验证 除了支持内置的验证规则validator包还支持自定义验证规则。我们可以通过实现validator.Func类型的函数来定义自己的验证规则。 利用validator包使binding注册自定义规则。
package mainimport (net/httpgithub.com/gin-gonic/gingithub.com/gin-gonic/gin/bindinggithub.com/go-playground/validator/v10
)type User struct {//2. 在参数binding上使用自定义的校验方法函数注册时的名称Name string form:name binding:NotNullAndAdminAge int form:age binding:gte0,lte100Email string form:email binding:email
}// 1. 自定义校验方法
// func notNullAndAdmin(c *validator.Validate, topStruct reflect.Value, curStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
func notNullAndAdmin(c validator.FieldLevel) bool {value : c.Field().String()//字段不能为空并且不等于adminreturn value ! !(value admin)
}func main() {r : gin.Default()//3.将我们自定义的校验方法注册到validator中if v, ok : binding.Validator.Engine().(*validator.Validate); ok {v.RegisterValidation(NotNullAndAdmin, notNullAndAdmin)}r.GET(/check, func(c *gin.Context) {var u Userif err : c.ShouldBind(u); err ! nil {c.String(http.StatusBadRequest, err.Error())}c.String(http.StatusOK, check pass)})r.Run()
} 利用validator包使validate注册自定义规则。
package mainimport (net/httpgithub.com/gin-gonic/gingithub.com/go-playground/validator/v10
)type User struct {//2. 在参数binding上使用自定义的校验方法函数注册时的名称Name string form:name validate:NotNullAndAdminAge int form:age validate:gte0,lte100Email string form:email validate:email
}// 1. 自定义校验方法
// func notNullAndAdmin(c *validator.Validate, topStruct reflect.Value, curStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
func notNullAndAdmin(c validator.FieldLevel) bool {value : c.Field().String()//字段不能为空并且不等于adminreturn value ! !(value admin)
}func main() {r : gin.Default()r.GET(/check, func(c *gin.Context) {var u Userif err : c.ShouldBind(u); err ! nil {c.String(http.StatusBadRequest, err.Error())}//3.将我们自定义的校验方法注册到validator中validate : validator.New()validate.RegisterValidation(NotNullAndAdmin, notNullAndAdmin)//数据校验err : validate.Struct(u)if err ! nil {c.String(http.StatusBadRequest, err.Error())}c.String(http.StatusOK, check pass)})r.Run()
} 原理是 通过反射获取struct中的tag根据不同的验证规则进行验证。 三. 多语言翻译验证 validator库本身使支持国际化的可以借助相应的语言包实现多语言翻译验证。 验证器使用的是
go get gopkg.in/go-playground/validator.v9 翻译器
github.com/go-playground/universal-translator 验证器注册翻译器
gopkg.in/go-playground/validator.v9/translations/en
gopkg.in/go-playground/validator.v9/translations/zh
gopkg.in/go-playground/validator.v9/translations/zh_tw 例如当业务系统对验证信息有特殊需求时返回信息需要自定义手机端返回的信息需要时中文而pc端发挥返回的信息需要是英文如何做到请求一个借口满足上述三种情况。
package mainimport (fmtnet/httpgithub.com/gin-gonic/gingithub.com/go-playground/locales/engithub.com/go-playground/locales/zhgithub.com/go-playground/locales/zh_Hant_TWut github.com/go-playground/universal-translatorgopkg.in/go-playground/validator.v9en_translations gopkg.in/go-playground/validator.v9/translations/enzh_translations gopkg.in/go-playground/validator.v9/translations/zhzh_tw_translations gopkg.in/go-playground/validator.v9/translations/zh_tw
)var (Uni *ut.UniversalTranslatorValidate *validator.ValidateTrans ut.Translator
)type User struct {Name string form:name validate:requiredTagline string form:tag_line validate:required,lt10Tagline2 string form:tag_line2 validate:required,gt1
}func main() {en : en.New()zh : zh.New()zh_tw : zh_Hant_TW.New()Uni ut.New(en, zh, zh_tw)Validate validator.New()r : gin.Default()r.GET(/check, registerTranslation(), startPage)r.Run()
}func registerTranslation() gin.HandlerFunc {return func(c *gin.Context) {//获得参数locale : c.DefaultQuery(locale, zh)//翻译器Trans, _ Uni.GetTranslator(locale)//验证器注册翻译器switch locale {case zh:zh_translations.RegisterDefaultTranslations(Validate, Trans)case en:en_translations.RegisterDefaultTranslations(Validate, Trans)case zh_tw:zh_tw_translations.RegisterDefaultTranslations(Validate, Trans)default:zh_translations.RegisterDefaultTranslations(Validate, Trans)}}
}func startPage(c *gin.Context) {//自定义错误内容Validate.RegisterTranslation(required, Trans, func(ut ut.Translator) error {return ut.Add(required, {0} must have val!, true)}, func(ut ut.Translator, fe validator.FieldError) string {t, _ : ut.T(required, fe.Field())return t})//验证数据var u Userif err : c.ShouldBind(u); err ! nil {c.String(http.StatusBadRequest, err.Error())return}fmt.Println(u)if err : Validate.Struct(u); err ! nil {errs : err.(validator.ValidationErrors)sliceErr : []string{}for _, e : range errs {//翻译错误sliceErr append(sliceErr, e.Translate(Trans))}c.String(http.StatusOK, fmt.Sprintf(%#v, sliceErr))return}c.String(http.StatusOK, fmt.Sprintf(%#v, u))
} 演示