go-zero内置验证
参考文档:
https://go-zero.dev/cn/docs/design/grammar#type%E8%AF%AD%E6%B3%95%E5%9D%97
tag定义和golang中json tag语法一样,除了json tag外,go-zero还提供了另外一些tag来实现对字段的描述, 详情见下表。
tag修饰符
常见参数校验描述
tag key | 描述 | 有效范围 | 示例 |
---|---|---|---|
optional | 定义当前字段为可选参数 | request | json:”name,optional |
options | 定义当前字段的枚举值,多个以竖线|隔开 | request | json:”gender,options=male” |
default | 定义当前字段默认值 | request | json:”gender,default=male” |
range | 定义当前字段数值范围 | request | json:”age,range=[0:120]” |
tag修饰符需要在tag value后以英文逗号,隔开
例子
type UserInfoGetRequest {
Name string `form:"name,optional"`
}
返回错误
error: value \"1\" for field \"name\" is not defined in options \"[li wang]\"
返回 json
格式错误需要定义错误处理,参考 错误处理 文档
返回例子:
{
"code": 1001,
"msg": "error: value \"1\" for field \"name\" is not defined in options \"[li wang]\""
}
第三方验证插件validator10
安装验证包
go get -u github.com/go-playground/validator/v10
新建文件 validator.go
项目根目录里新建文件 pkg/validator/validator.go
vim pkg/validator/validator.go
写入下面的内容
package validator
import (
"fmt"
"net/http"
"reflect"
"github.com/go-playground/locales/zh_Hans_CN"
unTrans "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
zhTrans "github.com/go-playground/validator/v10/translations/zh"
)
func Validate(data interface{}) (string, int) {
validate := validator.New()
uni := unTrans.New(zh_Hans_CN.New())
trans, _ := uni.GetTranslator("zh_Hans_CN")
err := zhTrans.RegisterDefaultTranslations(validate, trans)
if err != nil {
fmt.Println("err:", err)
}
validate.RegisterTagNameFunc(func(field reflect.StructField) string {
label := field.Tag.Get("label")
return label
})
err = validate.Struct(data)
if err != nil {
for _, v := range err.(validator.ValidationErrors) {
return v.Translate(trans), http.StatusUnprocessableEntity
}
}
return "", 0
}
修改模板
deploy/goctl/1.7.1/api/handler.tpl
加入下面的代码 ③ ④ ⑤ ⑥
注意① ②
处的代码,需要配合自定义模板和错误处理使用,参考 错误处理
和 模板修改
的文档③
处的代码,需要配合 pkg/validator/validator.go
自定义模板和错误处理使用
package {{.PkgName}}
import (
{{if .HasRequest}} {{end}}
"net/http"
"strconv"
"ytss_go_zero/common/errorx" // ①
"ytss_go_zero/common/response" // ②
{{.ImportPackages}}
{{if .HasRequest}}"ytss_go_zero/common/validator" // ③
"github.com/zeromicro/go-zero/rest/httpx" // ④
{{end}}
)
{{if .HasDoc}}{{.Doc}}{{end}}
func {{.HandlerName}}(svcCtx *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 {
httpx.Error(w, errorx.NewDefaultError(err.Error())) // ④ ①
return
}
{{if .HasRequest}}
// ③ validator10 验证
if errMsg, errCode := validator.Validate(req); errCode != 0 {
httpx.Error(w, errorx.NewCodeError(strconv.Itoa(errCode), errMsg)) // ④ ①
return
}
{{end}}
{{end}}
l := {{.LogicName}}.New{{.LogicType}}(r.Context(), svcCtx)
{{if .HasResp}}resp, {{end}}err := l.{{.Call}}({{if .HasRequest}}&req{{end}})
if err != nil {
httpx.Error(w, err) // ①
} else {
{{if .HasResp}}response.OkJson(w, "SUCCESS", resp, nil) //②{{else}}response.OkJson(w, "SUCCESS", nil, nil) //② {{end}}
}
}
}
修改 user.api
加入 tag
syntax = "v1"
info(
author: "user-api"
date: "2022-03-26"
desc: "api语法示例及语法说明"
)
import (
"user/user_data.api"
)
type UserInfoGetRequest {
UserId int64 `form:"userId" validate:"required,gte=0" label:"用戶id"` // ①
Name string `form:"name" validate:"required,gte=5" label:"姓名"` // ②
}
type UserInfoGetResponse {
UserId int64 `json:"userId"`
Nickname string `json:"nickname"`
}
// service block
@server(
group: user
prefix: api/v1
)
service user-api{
@doc "获取用户信息get"
@handler userInfoGet
get /user/info_get (UserInfoGetRequest) returns (UserInfoGetResponse)
}
生成API代码
指定生成模板API代码命令
cd user-api/api
指定生成模板
alias apigen=”goctl api go -api *.api -dir ../ –style=goZero –home=../../goctlTp
生成模板代码
app/api/admin/internal/handler/adminUser/admin_login_handler.go
package adminUser
import (
"net/http"
"strconv"
"ytss_go_zero/app/api/admin/internal/logic/adminUser"
"ytss_go_zero/app/api/admin/internal/svc"
"ytss_go_zero/app/api/admin/internal/types"
"ytss_go_zero/common/errorx" // ①
"ytss_go_zero/common/response" // ②
"ytss_go_zero/common/validator" // ③
"github.com/zeromicro/go-zero/rest/httpx" // ④
)
// 管理员登录
func AdminLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.LoginReq
if err := httpx.Parse(r, &req); err != nil {
httpx.Error(w, errorx.NewDefaultError(err.Error())) // ④ ①
return
}
// ③ validator10 验证
if errMsg, errCode := validator.Validate(req); errCode != 0 {
httpx.Error(w, errorx.NewCodeError(strconv.Itoa(errCode), errMsg)) // ④ ①
return
}
l := adminUser.NewAdminLoginLogic(r.Context(), svcCtx)
resp, err := l.AdminLogin(&req,r)
if err != nil {
httpx.Error(w, err) // ①
} else {
response.OkJson(w, "SUCCESS", resp, nil) //②
}
}
}
请求接口
curl -X GET http://127.0.0.1:8888/api/v1/user/info_get?userId=1&name=1
请求返回结果:
{
"code": 1001,
"msg": "姓名长度必须至少为5个字符"
}
最后编辑:海马 更新时间:2024-12-22 19:32