直接用正则最轻量,gin默认不支持手机号语义校验,推荐正则^1[3-9]d{9}$,它覆盖国内主流号段,足够应付web表单级校验,但不验证虚拟运营商号段或号段分配状态。

手机号校验用正则还是第三方库?
直接用正则最轻量,Gin 默认不带手机号语义校验,regexp 足够应付国内主流号段。别上 libphonenumber 这类重型库——除非你真要支持全球号码格式解析。
国内手机号正则建议用:^1[3-9]\d{9}$。注意:它不校验虚拟运营商号段(如 170/171),也不验证号段是否已分配,但对 Web 表单级校验足够可靠。
- 别写成
^1[3-9][0-9]{9}$——[0-9]和\d在 Go 的regexp中行为一致,但后者更通用 - 如果后端要对接短信平台,建议额外查一遍号段白名单(比如从工信部公开数据提取),正则只是第一道过滤
- Gin 的
binding不支持正则内联校验,得靠自定义Validator或中间件提前拦截
Gin 中绑定结构体时校验邮箱字段
Go 标准库 net/mail 的 ParseAddress 或 ParseAddressList 会过度严格(比如拒绝 user+tag@example.com),实际 Web 场景推荐用正则 + 简单 DNS 预检。
邮箱正则用这个:^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$。它覆盖常见合法格式,且避开 RFC 5322 全集的复杂性。
- Gin 结构体 tag 里写
binding:"required,email"是无效的——emailtag 仅检查格式是否含@和点,不校验域名部分,形同虚设 - 正确做法是在结构体方法里加
Validate(),或用go-playground/validator/v10第三方库扩展校验器 - 若启用了
ShouldBind,校验失败会返回400 Bad Request并附带默认错误信息,但字段名是原始 struct 字段名,不是 JSON key,容易让前端困惑
把手机号和邮箱校验塞进 Gin 的 Bind 流程
想让 c.ShouldBind(&req) 一步完成校验,必须用 go-playground/validator/v10 注册自定义函数,否则 Gin 自身无此能力。
示例注册方式:
import "github.com/go-playground/validator/v10"
var validate *validator.Validate
func init() {
validate = validator.New()
_ = validate.RegisterValidation("phone", func(fl validator.FieldLevel) bool {
return regexp.MustCompile(`^1[3-9]d{9}$`).MatchString(fl.Field().String())
})
_ = validate.RegisterValidation("email_format", func(fl validator.FieldLevel) bool {
return regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$`).MatchString(fl.Field().String())
})
}
- 注册后,在 struct tag 里写
validate:"required,phone"或validate:"required,email_format" - 别漏掉
validate.Struct(req)手动触发,ShouldBind默认只用内置规则,除非你替换了 Gin 的 validator 实例 - 错误提示默认是英文,需调用
validate.SetErrorTag("msg")并在 struct tag 里加msg:"手机号格式错误"才能自定义
前端传空字符串时校验失效怎么办
这是最常踩的坑:手机号或邮箱字段传 "",正则匹配失败,但 required 校验可能被绕过——因为 Go 的 string 类型零值就是 "",而 required 只判空指针或 nil slice/map,对空字符串无效。
- 必须显式加
validate:"required,min=11,max=11"(手机号)或validate:"required,min=5,max=254"(邮箱),用长度约束堵住空字符串 - 或者在 struct 字段上用指针类型:
*string,这样""和nil可区分,required才真正生效 - Gin 的
ShouldBindJSON对空字符串不做 trim,如果前端可能发前后空格,得自己加strings.TrimSpace预处理,不能依赖校验器自动去空格
required 的天然敌人,而是你没用对校验组合。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











