golang 利用reflect实现validator参数检测

golang 利用reflect实现validator参数检测

其实golang开源的validator 也有一些,但是出于学习的目的还是手动实现了一把,写的比较挫,轻喷。

实现思路

golang 的reflect可以获取到很多信息,对象的tag,tag的值,对象类型,对象的值等等

validator的实现基于reflect通过自定义tag,设定一组值作为validator的标准设定到tag的值下面,然后通过reflect包取到结构体每个字段的tag的值,和字段的值,两者进行匹配,不符合规则就直接报错返回,这样就实现了最简单的validator

代码如下,只定义了2种规则

  • “not empty”
  • “>0”
package main

import (
	"errors"
	"fmt"
	"reflect"
)

type Common struct {
	Name  string `validate:"not empty"`
	Class int    `validate:">1"`
}

func Validate(obj interface{}) error {
	st := reflect.TypeOf(obj)
	// 检测传入是否为结构体
	if st.Kind() != reflect.Struct {
		return errors.New("not struct")
	}
	v := reflect.ValueOf(obj)
	for i := 0; i < st.NumField(); i++ {
		field := st.Field(i)
		// 获取tag为alias的值
		if tagVal, ok := field.Tag.Lookup("validate"); ok {
			if tagVal == "" {
				continue
			}
			var val interface{}
			switch tagVal {
			case ">1":
				if v.Field(i).Kind() == reflect.Uint {
					if v.Field(i).Interface().(int) <= 0 {
						return failed(field.Name, val, tagVal)
					}
				}
			case "not empty":
				if v.Field(i).Kind() == reflect.String {
					val := v.Field(i).Interface().(string)
					if val == "" {
						return failed(field.Name, val, tagVal)
					}
				}
			}
		}
	}
	return nil
}

func failed(str string, val interface{}, expect string) error {
	err := errors.New(fmt.Sprintf("invalid %s,expect %v,acutal %s,", str, val, expect))
	fmt.Println(err.Error())
	return err
}

func main() {
	a := []Common{
		{
			Name:  "1",
			Class: 0,
		},
		{
			Name:  "",
			Class: 1,
		},
		{
			Name:  "1",
			Class: 1,
		},
	}
	for i, v := range a {
		err := Validate(v)
		if err != nil {
			fmt.Printf("index:%d,validate failed:%s\n", i, err.Error())
			continue
		}
		fmt.Printf("index:%d validate success\n", i)
	}
	return
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值