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

Go如何实现支持不同结构体入参的通用参数校验函数

Go通用结构体参数校验实现方案

方案1:基于反射适配你现有调用逻辑

动态读取结构体字段的需求可以直接用Go标准库的reflect包实现,不需要枚举所有结构体类型,代码实现如下:

import (
	"fmt"
	"reflect"
)

func CheckParams(input interface{}, paramsWithType map[string]string) error {
	// 获取输入参数的反射值
	val := reflect.ValueOf(input)
	// 校验传入参数是否为结构体类型
	if val.Kind() != reflect.Struct {
		return fmt.Errorf("input must be a struct")
	}

	// 遍历校验规则
	for fieldName, expectType := range paramsWithType {
		// 按字段名获取结构体字段值
		fieldVal := val.FieldByName(fieldName)
		// 字段不存在直接返回错误
		if !fieldVal.IsValid() {
			return fmt.Errorf("field %s not exist", fieldName)
		}

		// 校验字段类型是否符合预期
		actualType := fieldVal.Kind().String()
		if actualType != expectType {
			return fmt.Errorf("field %s type mismatch, expect %s, actual %s", fieldName, expectType, actualType)
		}

		// 校验非零值,可根据需求扩展其他校验规则
		if fieldVal.IsZero() {
			return fmt.Errorf("field %s can not be zero value", fieldName)
		}
	}
	return nil
}

你原有调用逻辑不需要修改,直接复用即可:

func main(){
	var input Interface1Input
	input.Age = 20
	input.Address = "北京市海淀区"
	paramsMap := map[string]string{
		"age": "int",
		"address": "string",
	}
	if err := CheckParams(input, paramsMap); err != nil {
		fmt.Println("校验失败:", err)
		return
	}
	fmt.Println("校验通过")
}

方案2:结构体Tag实现(业务场景推荐)

如果不需要每次调用灵活指定校验字段,更推荐用结构体Tag绑定校验规则,复用性和可维护性更高,示例如下:
定义结构体时添加校验Tag:

type Interface1Input struct {
	Name    string `validate:"required"`
	Age     int    `validate:"required,min=1"`
	Address string `validate:"required"`
}

type Interface2Input struct {
	Name   string `validate:"required"`
	Phone  string `validate:"required,len=11"`
	Gender string `validate:"required,oneof=男 女"`
}

校验函数读取Tag规则完成校验,不需要额外传入规则map:

func ValidateStruct(input interface{}) error {
	val := reflect.ValueOf(input)
	if val.Kind() != reflect.Struct {
		return fmt.Errorf("input must be a struct")
	}
	typ := val.Type()

	for i := 0; i < val.NumField(); i++ {
		field := typ.Field(i)
		tag := field.Tag.Get("validate")
		// 没有配置校验规则的字段直接跳过
		if tag == "" || tag == "-" {
			continue
		}
		fieldVal := val.Field(i)
		// 可根据tag值解析扩展更多规则,比如min、max、长度校验等
		if tag == "required" && fieldVal.IsZero() {
			return fmt.Errorf("field %s is required", field.Name)
		}
	}
	return nil
}

内容的提问来源于stack exchange,提问作者pkzz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 07:45:04