| 101 | } |
| 102 | |
| 103 | func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStruct { |
| 104 | v.structCache.lock.Lock() |
| 105 | defer v.structCache.lock.Unlock() // leave as defer! because if inner panics, it will never get unlocked otherwise! |
| 106 | |
| 107 | typ := current.Type() |
| 108 | |
| 109 | // could have been multiple trying to access, but once first is done this ensures struct |
| 110 | // isn't parsed again. |
| 111 | cs, ok := v.structCache.Get(typ) |
| 112 | if ok { |
| 113 | return cs |
| 114 | } |
| 115 | |
| 116 | cs = &cStruct{name: sName, fields: make([]*cField, 0), fn: v.structLevelFuncs[typ]} |
| 117 | |
| 118 | numFields := current.NumField() |
| 119 | rules := v.rules[typ] |
| 120 | |
| 121 | var ctag *cTag |
| 122 | var fld reflect.StructField |
| 123 | var tag string |
| 124 | var customName string |
| 125 | |
| 126 | for i := 0; i < numFields; i++ { |
| 127 | fld = typ.Field(i) |
| 128 | |
| 129 | if !v.privateFieldValidation && !fld.Anonymous && len(fld.PkgPath) > 0 { |
| 130 | continue |
| 131 | } |
| 132 | |
| 133 | if rtag, ok := rules[fld.Name]; ok { |
| 134 | tag = rtag |
| 135 | } else { |
| 136 | tag = fld.Tag.Get(v.tagName) |
| 137 | } |
| 138 | |
| 139 | if tag == skipValidationTag { |
| 140 | continue |
| 141 | } |
| 142 | |
| 143 | customName = fld.Name |
| 144 | |
| 145 | if v.hasTagNameFunc { |
| 146 | name := v.tagNameFunc(fld) |
| 147 | if len(name) > 0 || v.omitBlankFieldNames { |
| 148 | customName = name |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | // NOTE: cannot use shared tag cache, because tags may be equal, but things like alias may be different |
| 153 | // and so only struct level caching can be used instead of combined with Field tag caching |
| 154 | |
| 155 | if len(tag) > 0 { |
| 156 | ctag, _ = v.parseFieldTagsRecursive(tag, fld.Name, "", false) |
| 157 | } else { |
| 158 | // even if field doesn't have validations need cTag for traversing to potential inner/nested |
| 159 | // elements of the field. |
| 160 | ctag = new(cTag) |