参数校验:gvalid 标签(required/length/email/in 等)与错误返回

引言

参数不过校验就进业务,是大多数线上事故的来源。GoFrame 的 gvalid 组件把校验声明化:结构体字段写标签、数据过一遍规则,错误自动收集返回。

概念

  • 使用方式:结构体字段通过 v 标签声明规则,多个规则用 | 分隔;也可用 g.Validator() 对 map/对象即时校验。
  • 常用规则:required(必填)、length:6,16(长度区间)、min-length/max-lengthemailintegerin:1,2,3(枚举取值)、between:1,100 等;规则全集以官方文档 gvalid 章节为准。
  • 自定义消息:单条规则内用 # 追加错误消息,如 required#名称不能为空;多条规则可用 Messages 方法按顺序指定。
  • 错误返回:校验错误实现了 gvalid 的错误接口,可取出首条错误或错误 Map;HTTP 场景常直接把 err.Error() 返回前端。

代码示例

结构体校验(与 r.Parse 联动):

package main

import (
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
)

type RegisterReq struct {
	Name  string `v:"required|length:2,20"`          // 必填且长度 2~20
	Age   int    `v:"between:18,60"`                 // 取值 18~60
	Email string `v:"required|email"`                // 必填且为邮箱
	Role  string `v:"in:admin,user"`                 // 只能取枚举值
	Phone string `v:"phone#手机号格式不正确"`            // 自定义错误消息
}

func main() {
	s := g.Server()
	s.Group("/user", func(group *ghttp.RouterGroup) {
		group.POST("/register", func(r *ghttp.Request) {
			var req RegisterReq
			if err := r.Parse(&req); err != nil {
				r.Response.WriteJson(g.Map{"code": 1, "message": err.Error()})
				return
			}
			r.Response.WriteJson(g.Map{"code": 0, "message": "注册成功"})
		})
	})
	s.SetPort(8000)
	s.Run()
}

脱离 HTTP,直接用 g.Validator() 校验任意数据:

err := g.Validator().
	Rules("required|length:6,16").
	Data("123456").
	Messages("账号不能为空", "账号长度需为 6~16 位").
	Run(ctx) // ctx 为 context.Context

对 map 数据校验并拿到错误明细:

err := g.Validator().Data(g.Map{
	"name": r.Get("name").String(),
}).Rules(g.Map{
	"name": "required|length:2,20",
}).Run(ctx)

注意点

  • 规则名或参数写错(如 between:18 少一个边界)会直接报错,上线前用用例覆盖各规则。
  • 多条规则的错误消息按顺序与规则一一对应;# 方式最直观,推荐优先使用。
  • r.Parse 的自动校验依赖 v 标签;不带标签的字段只做类型绑定,不做校验。
  • 错误返回格式与"取首条还是全量"取决于调用方式,官方 gvalid 文档对错误对象结构有完整说明。

小结

v 标签让校验从"手写 if"变成"声明规则",配合 r.Parse 与规范路由几乎零成本接入。业务里组合 required/length/email/in 等规则已能覆盖绝大多数场景。完整规则表与自定义规则扩展以官方文档 goframe.org 的 gvalid 章节为准。

笔记加载中…