Compare commits

...

4 Commits

Author SHA1 Message Date
白茶清欢
0dfe2e742b
Merge fb022f54c074086fd6085cacd9731260089b8f3a into e3118cc378d263454098924ebbde7e8d1dd2e904 2026-01-25 09:57:25 +08:00
wanghaolong613
e3118cc378
refactor: for loop can be modernized using range over int (#4392)
Co-authored-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2026-01-25 00:51:11 +08:00
Artur Melanchyk
cad29c5e3f
perf(tree): reduce allocations in findCaseInsensitivePath (#4417)
Co-authored-by: Artur Melanchyk <13834276+arturmelanchyk@users.noreply.github.com>
2026-01-25 00:46:02 +08:00
白茶清欢
fb022f54c0 chore: longestCommonPrefix func in tree.go, fix variable name and add comment 2025-05-17 14:52:59 +08:00
8 changed files with 18 additions and 21 deletions

View File

@ -154,7 +154,7 @@ func runRequest(B *testing.B, r *Engine, method, path string) {
w := newMockWriter()
B.ReportAllocs()
B.ResetTimer()
for i := 0; i < B.N; i++ {
for B.Loop() {
r.ServeHTTP(w, req)
}
}

View File

@ -27,7 +27,7 @@ func (err SliceValidationError) Error() string {
}
var b strings.Builder
for i := 0; i < len(err); i++ {
for i := range len(err) {
if err[i] != nil {
if b.Len() > 0 {
b.WriteString("\n")
@ -58,7 +58,7 @@ func (v *defaultValidator) ValidateStruct(obj any) error {
case reflect.Slice, reflect.Array:
count := value.Len()
validateRet := make(SliceValidationError, 0)
for i := 0; i < count; i++ {
for i := range count {
if err := v.ValidateStruct(value.Index(i).Interface()); err != nil {
validateRet = append(validateRet, err)
}

View File

@ -119,7 +119,7 @@ func mapping(value reflect.Value, field reflect.StructField, setter setter, tag
tValue := value.Type()
var isSet bool
for i := 0; i < value.NumField(); i++ {
for i := range value.NumField() {
sf := tValue.Field(i)
if sf.PkgPath != "" && !sf.Anonymous { // unexported
continue

View File

@ -3677,22 +3677,22 @@ func BenchmarkGetMapFromFormData(b *testing.B) {
// Test case 3: Large dataset with many bracket keys
largeData := make(map[string][]string)
for i := 0; i < 100; i++ {
for i := range 100 {
key := fmt.Sprintf("ids[%d]", i)
largeData[key] = []string{fmt.Sprintf("value%d", i)}
}
for i := 0; i < 50; i++ {
for i := range 50 {
key := fmt.Sprintf("names[%d]", i)
largeData[key] = []string{fmt.Sprintf("name%d", i)}
}
for i := 0; i < 25; i++ {
for i := range 25 {
key := fmt.Sprintf("other[key%d]", i)
largeData[key] = []string{fmt.Sprintf("other%d", i)}
}
// Test case 4: Dataset with many non-matching keys (worst case)
worstCaseData := make(map[string][]string)
for i := 0; i < 100; i++ {
for i := range 100 {
key := fmt.Sprintf("nonmatching%d", i)
worstCaseData[key] = []string{fmt.Sprintf("value%d", i)}
}
@ -3728,7 +3728,7 @@ func BenchmarkGetMapFromFormData(b *testing.B) {
for _, bm := range benchmarks {
b.Run(bm.name, func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for b.Loop() {
_, _ = getMapFromFormData(bm.data, bm.key)
}
})

View File

@ -400,7 +400,7 @@ func TestConcurrentHandleContext(t *testing.T) {
var wg sync.WaitGroup
iterations := 200
wg.Add(iterations)
for i := 0; i < iterations; i++ {
for range iterations {
go func() {
req, err := http.NewRequest(http.MethodGet, "/", nil)
assert.NoError(t, err)

View File

@ -30,7 +30,7 @@ func rawStrToBytes(s string) []byte {
func TestBytesToString(t *testing.T) {
data := make([]byte, 1024)
for i := 0; i < 100; i++ {
for range 100 {
_, err := cRand.Read(data)
if err != nil {
t.Fatal(err)
@ -79,7 +79,7 @@ func RandStringBytesMaskImprSrcSB(n int) string {
}
func TestStringToBytes(t *testing.T) {
for i := 0; i < 100; i++ {
for range 100 {
s := RandStringBytesMaskImprSrcSB(64)
if !bytes.Equal(rawStrToBytes(s), StringToBytes(s)) {
t.Fatal("don't match")

13
tree.go
View File

@ -58,10 +58,12 @@ func (trees methodTrees) get(method string) *node {
return nil
}
// calculate the length of the longest common prefix of two strings
func longestCommonPrefix(a, b string) int {
i := 0
max_ := min(len(a), len(b))
for i < max_ && a[i] == b[i] {
// commonPrefixMaxLen is the min value of a and b's length.
commonPrefixMaxLen := min(len(a), len(b))
for i < commonPrefixMaxLen && a[i] == b[i] {
i++
}
return i
@ -671,12 +673,7 @@ walk: // Outer loop for walking the tree
func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) ([]byte, bool) {
const stackBufSize = 128
// Use a static sized buffer on the stack in the common case.
// If the path is too long, allocate a buffer on the heap instead.
buf := make([]byte, 0, stackBufSize)
if length := len(path) + 1; length > stackBufSize {
buf = make([]byte, 0, length)
}
buf := make([]byte, 0, max(stackBufSize, len(path)+1))
ciPath := n.findCaseInsensitivePathRec(
path,

View File

@ -162,7 +162,7 @@ func resolveAddress(addr []string) string {
// https://stackoverflow.com/questions/53069040/checking-a-string-contains-only-ascii-characters
func isASCII(s string) bool {
for i := 0; i < len(s); i++ {
for i := range len(s) {
if s[i] > unicode.MaxASCII {
return false
}