iris 中需同时满足字段导出、含 json tag 和 validate tag 才能触发校验;必须显式设置 app.validator = validator.new(),并手动处理 validationerrors 以返回结构化错误。

怎么给 struct 字段加自定义校验标签
Iris 本身不内置复杂校验逻辑,但支持通过 validator 第三方库(如 go-playground/validator/v10)注入校验器,并在 struct 字段上用 validate tag 声明规则。关键不是 Iris 提供了什么,而是你注册了哪个验证器、字段是否导出、tag 是否写对。
必须满足三个条件才能触发校验:
-
struct字段首字母大写(导出),否则ReadJSON会静默跳过 - 字段必须带
json:"xxx"tag,否则反序列化失败,校验无从谈起 - 必须额外加
validate:"xxx",比如validate:"required,email"
示例:
type User struct {
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required,gte=8,lte=32"`
Age uint8 `json:"age" validate:"gte=0,lte=150"`
}
注意:validate tag 和 json tag 是独立的,缺一不可。
为什么调用了 ReadJSON 却没触发校验
最常见原因是没给 app.Validator 赋值。Iris 不默认启用任何验证器,必须显式设置:
import "github.com/go-playground/validator/v10"
func main() {
app := iris.New()
app.Validator = validator.New() // ← 这行不能少
app.Post("/user", func(ctx iris.Context) {
var u User
if err := ctx.ReadJSON(&u); err != nil {
ctx.StatusCode(iris.StatusBadRequest)
ctx.JSON(iris.Map{"error": err.Error()})
return
}
// 校验通过才继续
})
}
其他容易踩的坑:
- 用
map[string]interface{}接收数据 →validate不生效,因为没 struct 字段可扫描 - 字段类型不匹配(比如 JSON 传字符串,struct 定义为
int)→ 在校验前就已报json: cannot unmarshal string into Go struct field - 忘记在
ReadJSON后检查返回的err→ 校验失败时err是*validator.InvalidValidationError或validator.ValidationErrors类型,需类型断言提取具体字段错误
如何返回结构化校验错误(含字段名和提示)
Iris 不自动格式化校验错误,你需要手动处理 validator.ValidationErrors。直接 err.Error() 只是扁平字符串,不利于前端解析。
推荐做法:写一个辅助函数,把 ValidationErrors 转成 map:
func parseValidatorErrors(err error) map[string]string {
errs := make(map[string]string)
if _, ok := err.(*validator.InvalidValidationError); ok {
return errs
}
if validationErrors, ok := err.(validator.ValidationErrors); ok {
for _, e := range validationErrors {
field := e.Field()
tag := e.Tag()
switch tag {
case "required":
errs[field] = "必填项"
case "email":
errs[field] = "邮箱格式不正确"
case "gte", "lte":
errs[field] = "数值超出范围"
default:
errs[field] = "格式错误"
}
}
}
return errs
}
然后在 handler 中调用:
if err := ctx.ReadJSON(&u); err != nil {
ctx.StatusCode(iris.StatusBadRequest)
ctx.JSON(iris.Map{"code": 400, "errors": parseValidatorErrors(err)})
return
}
自定义验证函数怎么注册(比如手机号、身份证)
标准 validate tag 不支持业务级规则,需注册自定义函数。例如校验 11 位手机号:
v := validator.New()
v.RegisterValidation("phone", func(fl validator.FieldLevel) bool {
s := fl.Field().String()
return regexp.MustCompile(`^1[3-9]\d{9}$`).MatchString(s)
})
app.Validator = v
之后就能在 struct 中使用:
Phone string `json:"phone" validate:"required,phone"`
注意点:
- 注册必须在
app.Validator = v之前完成 - 函数名(
"phone")要和 tag 中一致,大小写敏感 - 自定义函数里不要 panic,
FieldLevel提供的是只读访问,别试图修改原始 struct - 正则匹配前先判空,避免
fl.Field().String()对 nil 指针 panic
真正容易被忽略的是:自定义验证函数的错误信息默认还是英文且不带字段上下文,如果要返回中文提示,得自己封装一层错误包装逻辑,而不是依赖 validator 默认输出。











