(t reflect.Type)
| 75 | } |
| 76 | |
| 77 | func (e *encoder) typeEncoder(t reflect.Type) encoderFunc { |
| 78 | entry := encoderEntry{ |
| 79 | typ: t, |
| 80 | dateFormat: e.dateFormat, |
| 81 | arrayFmt: e.arrayFmt, |
| 82 | root: e.root, |
| 83 | } |
| 84 | |
| 85 | if fi, ok := encoders.Load(entry); ok { |
| 86 | return fi.(encoderFunc) |
| 87 | } |
| 88 | |
| 89 | // To deal with recursive types, populate the map with an |
| 90 | // indirect func before we build it. This type waits on the |
| 91 | // real func (f) to be ready and then calls it. This indirect |
| 92 | // func is only used for recursive types. |
| 93 | var ( |
| 94 | wg sync.WaitGroup |
| 95 | f encoderFunc |
| 96 | ) |
| 97 | wg.Add(1) |
| 98 | fi, loaded := encoders.LoadOrStore(entry, encoderFunc(func(key string, v reflect.Value, writer *multipart.Writer) error { |
| 99 | wg.Wait() |
| 100 | return f(key, v, writer) |
| 101 | })) |
| 102 | if loaded { |
| 103 | return fi.(encoderFunc) |
| 104 | } |
| 105 | |
| 106 | // Compute the real encoder and replace the indirect func with it. |
| 107 | f = e.newTypeEncoder(t) |
| 108 | wg.Done() |
| 109 | encoders.Store(entry, f) |
| 110 | return f |
| 111 | } |
| 112 | |
| 113 | func (e *encoder) newTypeEncoder(t reflect.Type) encoderFunc { |
| 114 | if t.ConvertibleTo(reflect.TypeOf(time.Time{})) { |
no test coverage detected