@@ -31,6 +31,48 @@ const (
3131 structErrMsg = "Struct:%s\n "
3232)
3333
34+ var structPool * pool
35+
36+ // Pool holds a channelStructErrors.
37+ type pool struct {
38+ pool chan * StructErrors
39+ }
40+
41+ // NewPool creates a new pool of Clients.
42+ func newPool (max int ) * pool {
43+ return & pool {
44+ pool : make (chan * StructErrors , max ),
45+ }
46+ }
47+
48+ // Borrow a StructErrors from the pool.
49+ func (p * pool ) Borrow () * StructErrors {
50+ var c * StructErrors
51+
52+ select {
53+ case c = <- p .pool :
54+ default :
55+ c = & StructErrors {
56+ Errors : map [string ]* FieldError {},
57+ StructErrors : map [string ]* StructErrors {},
58+ }
59+ }
60+
61+ return c
62+ }
63+
64+ // Return returns a StructErrors to the pool.
65+ func (p * pool ) Return (c * StructErrors ) {
66+
67+ // c.Struct = ""
68+
69+ select {
70+ case p .pool <- c :
71+ default :
72+ // let it go, let it go...
73+ }
74+ }
75+
3476type cachedTags struct {
3577 keyVals [][]string
3678 isOrVal bool
@@ -188,6 +230,9 @@ type Validate struct {
188230
189231// New creates a new Validate instance for use.
190232func New (tagName string , funcs map [string ]Func ) * Validate {
233+
234+ structPool = newPool (10 )
235+
191236 return & Validate {
192237 tagName : tagName ,
193238 validationFuncs : funcs ,
@@ -201,6 +246,16 @@ func (v *Validate) SetTag(tagName string) {
201246 v .tagName = tagName
202247}
203248
249+ // SetStructPoolMax sets the struct pools max size. this may be usefull for fine grained
250+ // performance tuning towards your application, however, the default should be fine for
251+ // nearly all cases. only increase if you have a deeply nested struct structure.
252+ // NOTE: this method is not thread-safe
253+ // NOTE: this is only here to keep compatibility with v5, in v6 the method will be removed
254+ // and the max pool size will be passed into the New function
255+ func (v * Validate ) SetMaxStructPoolSize (max int ) {
256+ structPool = newPool (max )
257+ }
258+
204259// AddFunction adds a validation Func to a Validate's map of validators denoted by the key
205260// NOTE: if the key already exists, it will get replaced.
206261// NOTE: this method is not thread-safe
@@ -260,11 +315,8 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
260315 structCache .Set (structType , cs )
261316 }
262317
263- validationErrors := & StructErrors {
264- Struct : structName ,
265- Errors : map [string ]* FieldError {},
266- StructErrors : map [string ]* StructErrors {},
267- }
318+ validationErrors := structPool .Borrow ()
319+ validationErrors .Struct = structName
268320
269321 for i := 0 ; i < numFields ; i ++ {
270322
@@ -360,6 +412,7 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
360412 }
361413
362414 if len (validationErrors .Errors ) == 0 && len (validationErrors .StructErrors ) == 0 {
415+ structPool .Return (validationErrors )
363416 return nil
364417 }
365418
0 commit comments