如何在go-playground/validator自定义校验中获取其他字段datetime标签参数
问题描述
我正在使用go-playground/validator包对Go中的结构体进行校验,结构体定义如下:
type GetLogRequest struct { CreatedAtMin string `query:"created_at_min" validate:"omitempty,datetime=2006-01-02"` CreatedAtMax string `query:"created_at_max" validate:"omitempty,datetime=2006-01-02,date_greater_than=CreatedAtMin"` }
CreatedAtMin和CreatedAtMax字段通过datetime标签定义了日期格式,我希望在自定义校验函数中复用该格式,当前自定义校验函数框架如下:
func validateDateGreaterThan(fl validator.FieldLevel) bool { dateMax, err := time.Parse("2006-01-02", fl.Field().String()) if err != nil { return false } dateMin, err := time.Parse("2006-01-02", fl.Parent().FieldByName(fl.Param()).String()) if err != nil { return false } return dateMin.After(dateMax) }
需要实现:在自定义校验函数中获取其他字段datetime校验标签的参数,替代time.Parse中的硬编码格式。
解决方案
可以通过解析字段的validate标签动态提取datetime格式参数,无需硬编码。具体实现步骤如下:
1. 编写标签解析工具函数
先实现一个辅助函数,从validate标签字符串中提取datetime对应的格式值:
import "strings" func extractDateFormat(validateTag string) string { for _, tagPart := range strings.Split(validateTag, ",") { if strings.HasPrefix(tagPart, "datetime=") { return strings.TrimPrefix(tagPart, "datetime=") } } return "" }
2. 修改自定义校验函数
在校验函数中,分别获取当前字段和对比字段的datetime格式,再用该格式解析时间:
import ( "time" "github.com/go-playground/validator/v10" ) func validateDateGreaterThan(fl validator.FieldLevel) bool { // 获取当前字段的datetime格式 currentFieldTag := fl.StructField().Tag.Get("validate") currentDateFormat := extractDateFormat(currentFieldTag) if currentDateFormat == "" { return false } // 解析当前字段的时间值 currentDateStr := fl.Field().String() currentDate, err := time.Parse(currentDateFormat, currentDateStr) if err != nil { return false } // 获取对比字段的信息 targetFieldName := fl.Param() targetField, ok := fl.Parent().Type().FieldByName(targetFieldName) if !ok { return false } // 获取对比字段的datetime格式 targetFieldTag := targetField.Tag.Get("validate") targetDateFormat := extractDateFormat(targetFieldTag) if targetDateFormat == "" { return false } // 解析对比字段的时间值 targetDateStr := fl.Parent().FieldByName(targetFieldName).String() targetDate, err := time.Parse(targetDateFormat, targetDateStr) if err != nil { return false } // 校验时间逻辑:CreatedAtMax 需大于 CreatedAtMin,所以返回 currentDate.After(targetDate) return currentDate.After(targetDate) }
关键说明
- 辅助函数
extractDateFormat通过拆分validate标签的逗号分隔项,匹配datetime=前缀来提取格式字符串。 - 若字段未定义
datetime标签,extractDateFormat返回空字符串,此时校验函数直接返回false,可根据业务需求调整该场景的处理逻辑。 - 注意校验逻辑的正确性:原函数中
dateMin.After(dateMax)逻辑有误,正确逻辑应为CreatedAtMax(当前字段)晚于CreatedAtMin(对比字段),即currentDate.After(targetDate)。
内容的提问来源于stack exchange,提问作者Edwyn Rangel
相关产品推荐
相关产品推荐

