func collectTags(t reflect.Type, tag string, ignoreTypes []string, keys *map[string]struct{}) {
	switch t.Kind() {

	case reflect.Array, reflect.Slice, reflect.Map, reflect.Ptr:
		collectTags(t.Elem(), tag, ignoreTypes, keys)

	case reflect.Struct:
		for i := 0; i < t.NumField(); i++ {
			field := t.Field(i)

			fieldTag := field.Tag.Get(tag)
			var fieldTagKey string

			ignoredType := false
			for _, it := range ignoreTypes {
				if field.Type.String() == it {
					ignoredType = true
					break
				}
			}

			if fieldTag == "-" || ignoredType {
				continue
			}

			if len(fieldTag) > 0 {
				fieldTagKey = strings.Split(fieldTag, ",")[0]
			} else {
				fieldTagKey = strings.ToLower(field.Name)
			}

			(*keys)[fieldTagKey] = struct{}{}
			collectTags(field.Type, tag, ignoreTypes, keys)
		}
	}
}
// collectTags returns a set of keys for a specified struct tag. If no tag is
// specified for a particular field of the argument struct type, then the
// all-lowercase field name is used as per Go tag conventions. If the tag
// specified is not the name a conventionally formatted go struct tag, then the
// results of this function are invalid. Values of invalid kinds result in no
// processing.
collectTags returns a set of keys for a specified struct tag. If no tag is
specified for a particular field of the argument struct type, then the
all-lowercase field name is used as per Go tag conventions. If the tag
specified is not the name a conventionally formatted go struct tag, then the
results of this function are invalid. Values of invalid kinds result in no
processing.
// collectTags returns a set of keys for a specified struct tag . If no tag is // specified for a particular field of the argument struct type then the // all - lowercase field name is used as per Go tag conventions . If the tag // specified is not the name a conventionally formatted go struct tag then the // results of this function are invalid . Values of invalid kinds result in no // processing .
func collectTags(t reflect.Type, tag string, ignoreTypes []string, keys *map[string]struct{}) {
	switch t.Kind() {
	case reflect.Array, reflect.Slice, reflect.Map, reflect.Ptr:
		collectTags(t.Elem(), tag, ignoreTypes, keys)
	case reflect.Struct:
		for i := 0; i < t.NumField(); i++ {
			field := t.Field(i)
			fieldTag := field.Tag.Get(tag)
			var fieldTagKey string
			ignoredType := false
			for _, it := range ignoreTypes {
				if field.Type.String() == it {
					ignoredType = true
					break
				}
			}
			if fieldTag == "-" || ignoredType {
				continue
			}
			if len(fieldTag) > 0 {
				fieldTagKey = strings.Split(fieldTag, ",")[0]
			} else {
				fieldTagKey = strings.ToLower(field.Name)
			}
			(*keys)[fieldTagKey] = struct{}{}
			collectTags(field.Type, tag, ignoreTypes, keys)
		}
	}
}
func collectTags ( t reflect . Type , tag string , ignoreTypes [ ] string , keys * map [ string ] struct { } ) { switch t . Kind ( ) { case reflect . Array , reflect . Slice , reflect . Map , reflect . Ptr : collectTags ( t . Elem ( ) , tag , ignoreTypes , keys ) case reflect . Struct : for i := 0 ; i < t . NumField ( ) ; i ++ { field := t . Field ( i ) fieldTag := field . Tag . Get ( tag ) var fieldTagKey string ignoredType := false for _ , it := range ignoreTypes { if field . Type . String ( ) == it { ignoredType = true break } } if fieldTag == " " || ignoredType { continue } if len ( fieldTag ) > 0 { fieldTagKey = strings . Split ( fieldTag , " " ) [ 0 ] } else { fieldTagKey = strings . ToLower ( field . Name ) } ( * keys ) [ fieldTagKey ] = struct { } { } collectTags ( field . Type , tag , ignoreTypes , keys ) } } }
collectTags returns a set of keys for a specified struct tag.
collectTags returns a set of keys for a specified struct tag .