func (mv *Validator) validateVar(v interface{}, tag string) error {
	tags, err := mv.parseTags(tag)
	if err != nil {
		return err
	}
	errs := make(ErrorArray, 0, len(tags))
	for _, t := range tags {
		if err := t.Fn(v, t.Param); err != nil {
			errs = append(errs, err)
		}
	}
	if len(errs) > 0 {
		return errs
	}
	return nil
}
validateVar validates one single variable
package validator
import (
	"bytes"
	"errors"
	"fmt"
	"reflect"
	"regexp"
	"strings"
)
type TextErr struct {
	Err error
}
func (t TextErr) Error() string {
	return t.Err.Error()
}
func (t TextErr) MarshalText() ([]byte, error) {
	return []byte(t.Err.Error()), nil
}
var (
	ErrZeroValue = TextErr{errors.New("zero value")}
	ErrMin = TextErr{errors.New("less than min")}
	ErrMax = TextErr{errors.New("greater than max")}
	ErrLen = TextErr{errors.New("invalid length")}
	ErrRegexp = TextErr{errors.New("regular expression mismatch")}
	ErrUnsupported = TextErr{errors.New("unsupported type")}
	ErrBadParameter = TextErr{errors.New("bad parameter")}
	ErrUnknownTag = TextErr{errors.New("unknown tag")}
	ErrInvalid = TextErr{errors.New("invalid value")}
	ErrCannotValidate = TextErr{errors.New("cannot validate unexported struct")}
)
type ErrorMap map[string]ErrorArray
func (err ErrorMap) Error() string {
	var b bytes.Buffer
	for k, errs := range err {
		if len(errs) > 0 {
			b.WriteString(fmt.Sprintf("%s: %s, ", k, errs.Error()))
		}
	}
	return strings.TrimSuffix(b.String(), ", ")
}
type ErrorArray []error
func (err ErrorArray) Error() string {
	var b bytes.Buffer
	for _, errs := range err {
		b.WriteString(fmt.Sprintf("%s, ", errs.Error()))
	}
	errs := b.String()
	return strings.TrimSuffix(errs, ", ")
}
type ValidationFunc func(v interface{}, param string) error
type Validator struct {
	validationFuncs map[string]ValidationFunc
	tagName string
	printJSON bool
}
var defaultValidator = NewValidator()
func NewValidator() *Validator {
	return &Validator{
		tagName: "validate",
		validationFuncs: map[string]ValidationFunc{
			"nonzero": nonzero,
			"len":     length,
			"min":     min,
			"max":     max,
			"regexp":  regex,
			"nonnil":  nonnil,
		},
		printJSON: false,
	}
}
func SetTag(tag string) {
	defaultValidator.SetTag(tag)
}
func (mv *Validator) SetTag(tag string) {
	mv.tagName = tag
}
func WithTag(tag string) *Validator {
	return defaultValidator.WithTag(tag)
}
func (mv *Validator) WithTag(tag string) *Validator {
	v := mv.copy()
	v.SetTag(tag)
	return v
}
func SetPrintJSON(printJSON bool) {
	defaultValidator.SetPrintJSON(printJSON)
}
func (mv *Validator) SetPrintJSON(printJSON bool) {
	mv.printJSON = printJSON
}
func WithPrintJSON(printJSON bool) *Validator {
	return defaultValidator.WithPrintJSON(printJSON)
}
func (mv *Validator) WithPrintJSON(printJSON bool) *Validator {
	v := mv.copy()
	v.SetPrintJSON(printJSON)
	return v
}
func (mv *Validator) copy() *Validator {
	newFuncs := map[string]ValidationFunc{}
	for k, f := range mv.validationFuncs {
		newFuncs[k] = f
	}
	return &Validator{
		tagName:         mv.tagName,
		validationFuncs: newFuncs,
		printJSON:       mv.printJSON,
	}
}
func SetValidationFunc(name string, vf ValidationFunc) error {
	return defaultValidator.SetValidationFunc(name, vf)
}
func (mv *Validator) SetValidationFunc(name string, vf ValidationFunc) error {
	if name == "" {
		return errors.New("name cannot be empty")
	}
	if vf == nil {
		delete(mv.validationFuncs, name)
		return nil
	}
	mv.validationFuncs[name] = vf
	return nil
}
func Validate(v interface{}) error {
	return defaultValidator.Validate(v)
}
func (mv *Validator) Validate(v interface{}) error {
	m := make(ErrorMap)
	mv.deepValidateCollection(reflect.ValueOf(v), m, func() string {
		return ""
	})
	if len(m) > 0 {
		return m
	}
	return nil
}
func (mv *Validator) validateStruct(sv reflect.Value, m ErrorMap) error {
	kind := sv.Kind()
	if (kind == reflect.Ptr || kind == reflect.Interface) && !sv.IsNil() {
		return mv.validateStruct(sv.Elem(), m)
	}
	if kind != reflect.Struct && kind != reflect.Interface {
		return ErrUnsupported
	}
	st := sv.Type()
	nfields := st.NumField()
	for i := 0; i < nfields; i++ {
		if err := mv.validateField(st.Field(i), sv.Field(i), m); err != nil {
			return err
		}
	}
	return nil
}
func (mv *Validator) validateField(fieldDef reflect.StructField, fieldVal reflect.Value, m ErrorMap) error {
	tag := fieldDef.Tag.Get(mv.tagName)
	if tag == "-" {
		return nil
	}
	for (fieldVal.Kind() == reflect.Ptr || fieldVal.Kind() == reflect.Interface) && !fieldVal.IsNil() {
		fieldVal = fieldVal.Elem()
	}
	if !fieldDef.Anonymous && fieldDef.PkgPath != "" {
		return nil
	}
	var errs ErrorArray
	if tag != "" {
		var err error
		if fieldDef.PkgPath != "" {
			err = ErrCannotValidate
		} else {
			err = mv.validValue(fieldVal, tag)
		}
		if errarr, ok := err.(ErrorArray); ok {
			errs = errarr
		} else if err != nil {
			errs = ErrorArray{err}
		}
	}
	mv.deepValidateCollection(fieldVal, m, func() string {
		return fieldDef.Name
	})
	if len(errs) > 0 {
		n := fieldDef.Name
		if mv.printJSON {
			if jn := parseName(fieldDef.Tag.Get("json")); jn != "" {
				n = jn
			}
		}
		m[n] = errs
	}
	return nil
}
func (mv *Validator) deepValidateCollection(f reflect.Value, m ErrorMap, fnameFn func() string) {
	switch f.Kind() {
	case reflect.Interface, reflect.Ptr:
		if f.IsNil() {
			return
		}
		mv.deepValidateCollection(f.Elem(), m, fnameFn)
	case reflect.Struct:
		subm := make(ErrorMap)
		err := mv.validateStruct(f, subm)
		parentName := fnameFn()
		if err != nil {
			m[parentName] = ErrorArray{err}
		}
		for j, k := range subm {
			keyName := j
			if parentName != "" {
				keyName = parentName + "." + keyName
			}
			m[keyName] = k
		}
	case reflect.Array, reflect.Slice:
		switch f.Type().Elem().Kind() {
		case reflect.Struct, reflect.Interface, reflect.Ptr, reflect.Map, reflect.Array, reflect.Slice:
			for i := 0; i < f.Len(); i++ {
				mv.deepValidateCollection(f.Index(i), m, func() string {
					return fmt.Sprintf("%s[%d]", fnameFn(), i)
				})
			}
		}
	case reflect.Map:
		for _, key := range f.MapKeys() {
			mv.deepValidateCollection(key, m, func() string {
				return fmt.Sprintf("%s[%+v](key)", fnameFn(), key.Interface())
			})  
			value := f.MapIndex(key)
			mv.deepValidateCollection(value, m, func() string {
				return fmt.Sprintf("%s[%+v](value)", fnameFn(), key.Interface())
			})
		}
	}
}
func Valid(val interface{}, tags string) error {
	return defaultValidator.Valid(val, tags)
}
func (mv *Validator) Valid(val interface{}, tags string) error {
	if tags == "-" {
		return nil
	}
	v := reflect.ValueOf(val)
	if (v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface) && !v.IsNil() {
		return mv.validValue(v.Elem(), tags)
	}
	if v.Kind() == reflect.Invalid {
		return mv.validateVar(nil, tags)
	}
	return mv.validateVar(val, tags)
}
func (mv *Validator) validValue(v reflect.Value, tags string) error {
	if v.Kind() == reflect.Invalid {
		return mv.validateVar(nil, tags)
	}
	return mv.validateVar(v.Interface(), tags)
}