场景
表单验证
要求
具备常用的验证规则
只配置验证规则,不用写具体代码
实现
引入validate组件,及相关的翻译包(为了中文提示)
修改handler模板
具体实现
安装validate包 go get github.com/go-playground/validator/v10
安装翻译相关包 go get github.com/go-playground/universal-translator
编写validate的方法
func (svc ServiceContext) Validate(dataStruct interface{}) error {
zh_ch := zh.New()
validate := validator.New()
// 注册一个函数,获取struct tag里自定义的label作为字段名
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := fld.Tag.Get("label")
return name
})
uni := ut.New(zh_ch)
trans, _ := uni.GetTranslator("zh")
// 验证器注册翻译器
zh_translations.RegisterDefaultTranslations(validate, trans)
err := validate.Struct(dataStruct)
if err != nil {
for _, err := range err.(validator.ValidationErrors) {
return errors.New(err.Translate(trans))
}
}
return nil
}
编写handler中的拦截(直接放模板里面去)
func AccountLoginHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.AccountAndPasswordLoginReq
if err := httpx.Parse(r, &req); err != nil {
response.Response(w, nil, err)
return
}
validateErr := ctx.Validate(&req)
if validateErr != nil {
response.Response(w, nil, validateErr)
return
}
l := account.NewAccountLoginLogic(r.Context(), ctx, r)
resp, err := l.AccountLogin(&req)
response.Response(w, resp, err)
}
}
goctl 模板代码
# 模板路径 ~/.goctl/1.3.5/api
package {{.PkgName}}
import (
"net/http"
"iot/app/common/httpx/response"
{{if .RequestType}}
"github.com/zeromicro/go-zero/rest/httpx"
{{end}}
{{.ImportPackages}}
)
func {{.HandlerName}}(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
{{if .HasRequest}}var req types.{{.RequestType}}
if err := httpx.Parse(r, &req); err != nil {
response.Response(w, nil, err)
return
}
validateErr := ctx.Validate(&req)
if validateErr != nil {
response.Response(w, nil, validateErr)
return
}
{{end}}
l := {{.LogicName}}.New{{.LogicType}}(r.Context(), ctx)
{{if .HasResp}}resp, {{end}}err := l.{{.Call}}({{if .HasRequest}}&req{{end}})
{{if .HasResp}}response.Response(w, resp, err){{else}}response.Response(w, nil, err){{end}}
}
}
存在的问题
- 当前的验证方法写在了svc里面,修改的模板是全局模板,当其他api中svc没有定义validate的方法则会报错
- 最好是可以修改goctl的实现,加参数生成,比较灵活
网友评论