improve sliceValidateError.Error performance using switch and strings.Builder (#2765)
fix missing nil pointer check use simpler switch case add missing tests use for-loop instead of range add benchmark test codes
This commit is contained in:
		| @ -20,15 +20,27 @@ type defaultValidator struct { | ||||
|  | ||||
| type sliceValidateError []error | ||||
|  | ||||
| // Error concatenates all error elements in sliceValidateError into a single string separated by \n. | ||||
| func (err sliceValidateError) Error() string { | ||||
| 	var errMsgs []string | ||||
| 	for i, e := range err { | ||||
| 		if e == nil { | ||||
| 			continue | ||||
| 	n := len(err) | ||||
| 	switch n { | ||||
| 	case 0: | ||||
| 		return "" | ||||
| 	default: | ||||
| 		var b strings.Builder | ||||
| 		if err[0] != nil { | ||||
| 			fmt.Fprintf(&b, "[%d]: %s", 0, err[0].Error()) | ||||
| 		} | ||||
| 		errMsgs = append(errMsgs, fmt.Sprintf("[%d]: %s", i, e.Error())) | ||||
| 		if n > 1 { | ||||
| 			for i := 1; i < n; i++ { | ||||
| 				if err[i] != nil { | ||||
| 					b.WriteString("\n") | ||||
| 					fmt.Fprintf(&b, "[%d]: %s", i, err[i].Error()) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return b.String() | ||||
| 	} | ||||
| 	return strings.Join(errMsgs, "\n") | ||||
| } | ||||
|  | ||||
| var _ StructValidator = &defaultValidator{} | ||||
|  | ||||
							
								
								
									
										20
									
								
								binding/default_validator_benchmark_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								binding/default_validator_benchmark_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| package binding | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"strconv" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func BenchmarkSliceValidateError(b *testing.B) { | ||||
| 	const size int = 100 | ||||
| 	for i := 0; i < b.N; i++ { | ||||
| 		e := make(sliceValidateError, size) | ||||
| 		for j := 0; j < size; j++ { | ||||
| 			e[j] = errors.New(strconv.Itoa(j)) | ||||
| 		} | ||||
| 		if len(e.Error()) == 0 { | ||||
| 			b.Errorf("error") | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -16,6 +16,26 @@ func TestSliceValidateError(t *testing.T) { | ||||
| 		want string | ||||
| 	}{ | ||||
| 		{"has nil elements", sliceValidateError{errors.New("test error"), nil}, "[0]: test error"}, | ||||
| 		{"has zero elements", sliceValidateError{}, ""}, | ||||
| 		{"has one element", sliceValidateError{errors.New("test one error")}, "[0]: test one error"}, | ||||
| 		{"has two elements", | ||||
| 			sliceValidateError{ | ||||
| 				errors.New("first error"), | ||||
| 				errors.New("second error"), | ||||
| 			}, | ||||
| 			"[0]: first error\n[1]: second error", | ||||
| 		}, | ||||
| 		{"has many elements", | ||||
| 			sliceValidateError{ | ||||
| 				errors.New("first error"), | ||||
| 				errors.New("second error"), | ||||
| 				nil, | ||||
| 				nil, | ||||
| 				nil, | ||||
| 				errors.New("last error"), | ||||
| 			}, | ||||
| 			"[0]: first error\n[1]: second error\n[5]: last error", | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tt := range tests { | ||||
| 		t.Run(tt.name, func(t *testing.T) { | ||||
|  | ||||
		Reference in New Issue
	
	Block a user