( c *Cache, parentEmbed, childEmbed *structData, childIndex []int, name string, )
| 110 | } |
| 111 | |
| 112 | func (s *structData) findInEmbedded( |
| 113 | c *Cache, |
| 114 | parentEmbed, childEmbed *structData, |
| 115 | childIndex []int, |
| 116 | name string, |
| 117 | ) *structField { |
| 118 | // Set current parent/child data. This allows trySet to handle child fields |
| 119 | // and add them to our struct and to the parent as well if needed |
| 120 | s.curParent = parentEmbed |
| 121 | s.curChild = childEmbed |
| 122 | s.curChildIndex = childIndex |
| 123 | defer func() { |
| 124 | // Ensure to cleanup references |
| 125 | s.curParent = nil |
| 126 | if childEmbed.finished() { |
| 127 | // If the child can still have more fields to explore then keep it |
| 128 | // referened to look it up again if we need to |
| 129 | s.curChild = nil |
| 130 | s.curChildIndex = nil |
| 131 | } |
| 132 | }() |
| 133 | |
| 134 | // See if the child has already cached its fields. This is still important |
| 135 | // to check even if it's the s.unfinishedEmbedded because it may have |
| 136 | // explored new fields since the last time we visited it |
| 137 | for name, sf := range childEmbed.fields { |
| 138 | s.trySet(name, sf) |
| 139 | } |
| 140 | |
| 141 | // Recheck if we have what we needed from the above sync |
| 142 | if sf := s.fields[name]; sf != nil { |
| 143 | return sf |
| 144 | } |
| 145 | |
| 146 | // Try finding in the child again in case it hasn't finished |
| 147 | if !childEmbed.finished() { |
| 148 | if childEmbed.structField(c, s, name) != nil { |
| 149 | return s.fields[name] |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | return nil |
| 154 | } |
| 155 | |
| 156 | func (s *structData) trySet(name string, sf *structField) { |
| 157 | if _, ok := s.fields[name]; ok { |
no test coverage detected