binding.go
func validateStruct(errors Errors, obj interface{}) Errors {
	typ := reflect.TypeOf(obj)
	val := reflect.ValueOf(obj)

	if typ.Kind() == reflect.Ptr {
		typ = typ.Elem()
		val = val.Elem()
	}

	for i := 0; i < typ.NumField(); i++ {
		field := typ.Field(i)

		// Skip ignored and unexported fields in the struct
		if field.Tag.Get("form") == "-" || !val.Field(i).CanInterface() {
			continue
		}

		fieldValue := val.Field(i).Interface()
		zero := reflect.Zero(field.Type).Interface()

		// Validate nested and embedded structs (if pointer, only do so if not nil)
		if field.Type.Kind() == reflect.Struct ||
			(field.Type.Kind() == reflect.Ptr && !reflect.DeepEqual(zero, fieldValue) &&
				field.Type.Elem().Kind() == reflect.Struct) {
			errors = validateStruct(errors, fieldValue)
		}

		if strings.Index(field.Tag.Get("binding"), "required") > -1 {
			if reflect.DeepEqual(zero, fieldValue) {
				name := field.Name
				if j := field.Tag.Get("json"); j != "" {
					name = j
				} else if f := field.Tag.Get("form"); f != "" {
					name = f
				}
				errors.Add([]string{name}, RequiredError, "Required")
			}
		}
	}
	return errors
}
func validateStruct(errors Errors, obj interface{}) Errors {
	typ := reflect.TypeOf(obj)
	val := reflect.ValueOf(obj)

	if typ.Kind() == reflect.Ptr {
		typ = typ.Elem()
		val = val.Elem()
	}

	for i := 0; i < typ.NumField(); i++ {
		field := typ.Field(i)

		// Skip ignored and unexported fields in the struct
		if field.Tag.Get("form") == "-" || !val.Field(i).CanInterface() {
			continue
		}

		fieldValue := val.Field(i).Interface()
		zero := reflect.Zero(field.Type).Interface()

		// Validate nested and embedded structs (if pointer, only do so if not nil)
		if field.Type.Kind() == reflect.Struct ||
			(field.Type.Kind() == reflect.Ptr && !reflect.DeepEqual(zero, fieldValue) &&
				field.Type.Elem().Kind() == reflect.Struct) {
			errors = validateStruct(errors, fieldValue)
		}

		if strings.Index(field.Tag.Get("binding"), "required") > -1 {
			if reflect.DeepEqual(zero, fieldValue) {
				name := field.Name
				if j := field.Tag.Get("json"); j != "" {
					name = j
				} else if f := field.Tag.Get("form"); f != "" {
					name = f
				}
				errors.Add([]string{name}, RequiredError, "Required")
			}
		}
	}
	return errors
}
func validateStruct ( errors Errors , obj interface { } ) Errors { typ := reflect . TypeOf ( obj ) val := reflect . ValueOf ( obj ) if typ . Kind ( ) == reflect . Ptr { typ = typ . Elem ( ) val = val . Elem ( ) } for i := 0 ; i < typ . NumField ( ) ; i ++ { field := typ . Field ( i ) // Skip ignored and unexported fields in the struct if field . Tag . Get ( " " ) == " " || ! val . Field ( i ) . CanInterface ( ) { continue } fieldValue := val . Field ( i ) . Interface ( ) zero := reflect . Zero ( field . Type ) . Interface ( ) // Validate nested and embedded structs (if pointer, only do so if not nil) if field . Type . Kind ( ) == reflect . Struct || ( field . Type . Kind ( ) == reflect . Ptr && ! reflect . DeepEqual ( zero , fieldValue ) && field . Type . Elem ( ) . Kind ( ) == reflect . Struct ) { errors = validateStruct ( errors , fieldValue ) } if strings . Index ( field . Tag . Get ( " " ) , " " ) > - 1 { if reflect . DeepEqual ( zero , fieldValue ) { name := field . Name if j := field . Tag . Get ( " " ) ; j != " " { name = j } else if f := field . Tag . Get ( " " ) ; f != " " { name = f } errors . Add ( [ ] string { name } , RequiredError , " " ) } } } return errors }
// Performs required field checking on a struct
Performs required field checking on a struct