Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify SliceValidationError Error method #3910

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

1911860538
Copy link
Contributor

@1911860538 1911860538 commented Mar 29, 2024

Enhance code readability by replacing the original "switch statement and if conditionals" with a simple "for loop" to iterate over the error slice.

Below is my local test code:

default_validator.go

type SliceValidationError []error

// Error concatenates all error elements in SliceValidationError into a single string separated by \n.
func (err SliceValidationError) Error() string {
	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())
				}
			}
		}
		return b.String()
	}
}

func (err SliceValidationError) NewError() string {
	if len(err) == 0 {
		return ""
	}

	var b strings.Builder
	for i := 0; i < len(err); i++ {
		if err[i] != nil {
			if b.Len() > 0 {
				b.WriteString("\n")
			}
			b.WriteString("[" + strconv.Itoa(i) + "]: " + err[i].Error())
		}
	}
	return b.String()
}

default_validator_benchmark_test.go

package binding

import (
	"errors"
	"strconv"
	"testing"

	"github.com/stretchr/testify/assert"
)

func getSliceValidationError(n int) SliceValidationError {
	e := make(SliceValidationError, n)
	for i := 0; i < n; i++ {
		e[i] = errors.New(strconv.Itoa(i))
	}
	return e
}

func TestSameError(t *testing.T) {
	e0 := getSliceValidationError(0)
	assert.Equal(t, e0.Error(), e0.NewError())

	e1 := getSliceValidationError(1)
	assert.Equal(t, e1.Error(), e1.NewError())

	e10 := getSliceValidationError(10)
	assert.Equal(t, e10.Error(), e10.NewError())
}

func BenchmarkSliceValidationError0(b *testing.B) {
	e := getSliceValidationError(0)

	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		_ = e.Error()
	}
}

func BenchmarkSliceValidationNewError0(b *testing.B) {
	e := getSliceValidationError(0)

	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		_ = e.NewError()
	}
}

func BenchmarkSliceValidationError1(b *testing.B) {
	e := getSliceValidationError(1)

	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		_ = e.Error()
	}
}

func BenchmarkSliceValidationNewError1(b *testing.B) {
	e := getSliceValidationError(1)

	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		_ = e.NewError()
	}
}

func BenchmarkSliceValidationError10(b *testing.B) {
	e := getSliceValidationError(10)

	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		_ = e.Error()
	}
}

func BenchmarkSliceValidationNewError10(b *testing.B) {
	e := getSliceValidationError(10)

	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		_ = e.NewError()
	}
}

test output

=== RUN   TestSameError
--- PASS: TestSameError (0.00s)
PASS

Process finished with the exit code 0

benchmark output

goos: darwin
goarch: amd64
pkg: github.com/gin-gonic/gin/binding
cpu: Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz
BenchmarkSliceValidationError0
BenchmarkSliceValidationError0-8       	611569416	         1.911 ns/op	       0 B/op	       0 allocs/op
BenchmarkSliceValidationNewError0
BenchmarkSliceValidationNewError0-8    	614464096	         1.909 ns/op	       0 B/op	       0 allocs/op
BenchmarkSliceValidationError1
BenchmarkSliceValidationError1-8       	 5836453	       196.6 ns/op	      56 B/op	       3 allocs/op
BenchmarkSliceValidationNewError1
BenchmarkSliceValidationNewError1-8    	21680595	        51.82 ns/op	       8 B/op	       1 allocs/op
BenchmarkSliceValidationError10
BenchmarkSliceValidationError10-8      	  705206	      1609 ns/op	     440 B/op	      16 allocs/op
BenchmarkSliceValidationNewError10
BenchmarkSliceValidationNewError10-8   	 2226651	       530.6 ns/op	     248 B/op	       5 allocs/op
PASS

Process finished with the exit code 0

Copy link

codecov bot commented Mar 29, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 99.18%. Comparing base (3dc1cd6) to head (345707e).
Report is 35 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3910      +/-   ##
==========================================
- Coverage   99.21%   99.18%   -0.03%     
==========================================
  Files          42       43       +1     
  Lines        3182     2704     -478     
==========================================
- Hits         3157     2682     -475     
+ Misses         17       12       -5     
- Partials        8       10       +2     
Flag Coverage Δ
?
-tags "sonic avx" 99.17% <100.00%> (?)
-tags go_json 99.17% <100.00%> (?)
-tags nomsgpack 99.17% <100.00%> (?)
go-1.18 99.11% <100.00%> (-0.01%) ⬇️
go-1.19 99.18% <100.00%> (-0.03%) ⬇️
go-1.20 99.18% <100.00%> (-0.03%) ⬇️
go-1.21 99.18% <100.00%> (-0.03%) ⬇️
go-1.22 99.18% <100.00%> (?)
macos-latest 99.18% <100.00%> (-0.03%) ⬇️
ubuntu-latest 99.18% <100.00%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant