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

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 77a8f5e
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 77a8f5e

Please sign in to comment.