如何在Go validator自定义校验函数中获取结构体名称
问题:自定义校验函数中获取结构体名称以复用数据库校验
用户定义了如下结构体与自定义校验函数,需要在校验函数中动态获取字段所属的结构体名称,以此匹配对应的数据库表名,避免硬编码表名,实现校验函数的复用:
结构体定义:
type User struct { Name string `validate:"custom_validation"` }
自定义校验函数:
func customFunc(fl validator.FieldLevel) bool { // 需要在此处获取结构体名称 // 执行数据库校验操作... return true } validate.RegisterValidation("custom_validation", customFunc)
解决方案
通过validator.FieldLevel的API结合Go的反射机制,可以实现需求,具体步骤如下:
- 获取结构体名称
在customFunc中,调用fl.Struct()获取当前字段所属的结构体实例,再通过反射获取其类型信息,最终得到结构体名称:
structType := reflect.TypeOf(fl.Struct()).Elem() structName := structType.Name() // 示例中得到的是"User"
- 结构体名称转数据库表名(可选)
如果需要将驼峰式结构体名称转换为数据库常用的下划线命名(比如User转users、AdminUser转admin_users),可以添加辅助转换函数:
func structNameToTableName(name string) string { var result strings.Builder for i, r := range name { if unicode.IsUpper(r) && i > 0 { result.WriteRune('_') } result.WriteRune(unicode.ToLower(r)) } return result.String() }
- 完整校验函数示例
import ( "reflect" "strings" "unicode" "github.com/go-playground/validator/v10" ) func customFunc(fl validator.FieldLevel) bool { // 获取结构体类型与名称 structType := reflect.TypeOf(fl.Struct()).Elem() structName := structType.Name() // 转换为数据库表名 tableName := structNameToTableName(structName) // 执行数据库校验逻辑(示例) // 比如查询表中是否存在当前字段值: // var count int // err := db.QueryRow("SELECT COUNT(*) FROM "+tableName+" WHERE name = ?", fl.Field().String()).Scan(&count) // if err != nil || count > 0 { // return false // } return true } func structNameToTableName(name string) string { var result strings.Builder for i, r := range name { if unicode.IsUpper(r) && i > 0 { result.WriteRune('_') } result.WriteRune(unicode.ToLower(r)) } return result.String() } // 注册校验器 var validate *validator.Validate func init() { validate = validator.New() validate.RegisterValidation("custom_validation", customFunc) }
内容的提问来源于stack exchange,提问作者Bens
相关产品推荐
相关产品推荐

