diff --git a/baked_in.go b/baked_in.go index a482196..231b78e 100644 --- a/baked_in.go +++ b/baked_in.go @@ -141,18 +141,24 @@ var ( } ) -var oneofValCache = map[string][]string{} -var oneofValCacheLock = sync.Mutex{} +var oneofValsCache = map[string][]string{} +var oneofValsCacheRWLock = sync.RWMutex{} -func isOneOf(fl FieldLevel) bool { - param := fl.Param() - oneofValCacheLock.Lock() - vals, ok := oneofValCache[param] +func parseOneOfParam2(s string) []string { + oneofValsCacheRWLock.RLock() + vals, ok := oneofValsCache[s] + oneofValsCacheRWLock.RUnlock() if !ok { - vals = strings.Fields(param) - oneofValCache[param] = vals + oneofValsCacheRWLock.Lock() + vals = strings.Fields(s) + oneofValsCache[s] = vals + oneofValsCacheRWLock.Unlock() } - oneofValCacheLock.Unlock() + return vals +} + +func isOneOf(fl FieldLevel) bool { + vals := parseOneOfParam2(fl.Param()) field := fl.Field() diff --git a/benchmarks_test.go b/benchmarks_test.go index 3e7e79f..5ac871f 100644 --- a/benchmarks_test.go +++ b/benchmarks_test.go @@ -1184,3 +1184,27 @@ func BenchmarkStructComplexFailureParallel(b *testing.B) { } }) } + +type TestOneof struct { + Color string `validate:"oneof=red green"` +} + +func BenchmarkOneof(b *testing.B) { + w := &TestOneof{Color: "green"} + val := New() + for i := 0; i < b.N; i++ { + val.Struct(w) + } +} + +func BenchmarkOneofParallel(b *testing.B) { + w := &TestOneof{Color: "green"} + val := New() + + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + val.Struct(w) + } + }) +}