介绍
dive 是 Gin 依赖的 go-playground/validator 库中专门用于切片(slice)/数组的校验标签,作用是「穿透切片外层,对切片内的每个元素执行后续校验规则」。
一、核心场景:切片必传 + 元素规则校验
场景 1:仅要求「切片必传 + 每个元素长度 ≥1」
需求拆解:
- 必传
tags 字段(不允许 JSON 中缺失该字段,即切片不能为 nil)
- 切片内每个
tag 的字符串长度 ≥1(不允许空字符串元素)
实现代码:
1 2 3 4 5 6
| type TagsInput struct { Tags []string `json:"tags" binding:"required,dive,min=1"` }
|
满足条件
1 2 3
| {"tags": ["go", "gin", "validator"]} {"tags": ["a"]} {"tags": []}
|
错误请求
1 2
| {} {"tags": ["", "gin"]}
|
场景 2:要求「切片必传 + 切片长度 ≥1 + 每个元素长度 ≥1」
需求拆解:
- 比场景 1 多了「切片非空」要求
- 必传
tags 字段(切片不能为 nil)
- 切片本身至少有 1 个元素(长度 ≥1)
- 每个
tag 的字符串长度 ≥1(元素非空)
实现代码
注意:两次 min=1 作用不同:
1 2 3 4 5
| type TagsInput struct { Tags []string `json:"tags" binding:"required,min=1,dive,min=1"` }
|
合法请求
1 2
| {"tags": ["go", "gin"]} {"tags": ["a"]}
|
错误请求
1 2 3
| {} {"tags": []} {"tags": ["", "gin"]}
|
二、关键知识点拆解
1. 两次 min=1 的区别(核心重点)
| 位置 |
作用层级 |
含义 |
示例(违反规则的情况) |
required 后、dive 前 |
切片级 |
要求切片的长度 ≥ N(此处 N=1) |
{"tags": []}(切片长度=0) |
dive 后 |
元素级 |
要求切片中每个元素满足 min=N(字符串长度 ≥N、数字 ≥N 等) |
{"tags": [""]}(元素长度=0) |
注意:min 是多类型兼容规则,对切片作用于长度,对字符串作用于字符数,对数字作用于数值大小。
2. dive 标签的核心作用
- 没有
dive 时,所有校验规则仅作用于切片本身(如是否存在、长度等),不关心元素;
- 加上
dive 后,后续的所有规则都会穿透到切片内部,逐个应用于每个元素;
- 若切片是嵌套结构体切片(如
[]User),dive 后会自动校验结构体的字段规则(无需额外配置)。
示例(嵌套结构体切片):
1 2 3 4 5 6 7 8 9
| type User struct { Name string `json:"name" binding:"required"` Age int `json:"age" binding:"gt=18"` }
type UserListInput struct { Users []User `json:"users" binding:"required,min=1,dive"` }
|
3. 常见误区
认为 required 能限制切片非空
说明:required 仅校验 切片字段存在(非 nil),空切片 [] 会通过 required 校验(需配合 min=1 限制切片长度)。
省略 dive 直接写元素规则
说明: 如 binding:"required,min=1" 仅作用于切片长度,不会校验元素;必须加 dive 才能让规则作用于元素。
重复 dive 或顺序错误
说明: dive 只需写一次,且必须在切片级规则之后、元素级规则之前(正确顺序:required → 切片规则 → dive → 元素规则)。
三、扩展场景(灵活组合规则)
场景:切片必传 + 元素是邮箱格式
1 2 3 4
| type EmailListInput struct { Emails []string `json:"emails" binding:"required,min=2,dive,email"` }
|
合法请求:
1
| {"emails": ["test1@example.com", "test2@example.com"]}
|
错误请求:
1 2
| {"emails": ["test1@example.com"]} {"emails": ["test1.example.com", "test2@example.com"]}
|
总结
| 业务需求 |
binding 规则 |
| 切片必传,元素无要求(允许空切片、空元素) |
required |
| 切片必传,元素非空(允许空切片) |
required,dive,min=1 |
| 切片必传 + 切片非空 + 元素非空 |
required,min=1,dive,min=1 |
| 切片必传 + 切片长度≥N + 元素满足特定格式 |
required,min=N,dive,元素规则(如 dive,email) |