You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 21:23:17