Skip to content

Commit

Permalink
improve sliceValidateError.Error performance using switch and strings…
Browse files Browse the repository at this point in the history
….Builder (#2765)

fix missing nil pointer check

use simpler switch case

add missing tests

use for-loop instead of range

add benchmark test codes
  • Loading branch information
zihengCat committed Jun 28, 2021
1 parent 1d0f938 commit e3ee01d
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 6 deletions.
24 changes: 18 additions & 6 deletions binding/default_validator.go
Expand Up @@ -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())
}
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())
}
}
}
errMsgs = append(errMsgs, fmt.Sprintf("[%d]: %s", i, e.Error()))
return b.String()
}
return strings.Join(errMsgs, "\n")
}

var _ StructValidator = &defaultValidator{}
Expand Down
20 changes: 20 additions & 0 deletions binding/default_validator_benchmark_test.go
@@ -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")
}
}
}
20 changes: 20 additions & 0 deletions binding/default_validator_test.go
Expand Up @@ -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) {
Expand Down

0 comments on commit e3ee01d

Please sign in to comment.