mirror of
https://github.com/gin-gonic/gin.git
synced 2026-07-14 15:11:18 +08:00
Compare commits
4 Commits
077a2f39c8
...
f9bd00a6b7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9bd00a6b7 | ||
|
|
28172fa682 | ||
|
|
46150257b3 | ||
|
|
e7693e67c2 |
4
.github/workflows/gin.yml
vendored
4
.github/workflows/gin.yml
vendored
@ -20,7 +20,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: "^1"
|
go-version: "^1"
|
||||||
- name: Setup golangci-lint
|
- name: Setup golangci-lint
|
||||||
@ -55,7 +55,7 @@ jobs:
|
|||||||
GOPROXY: https://proxy.golang.org
|
GOPROXY: https://proxy.golang.org
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go ${{ matrix.go }}
|
- name: Set up Go ${{ matrix.go }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go }}
|
go-version: ${{ matrix.go }}
|
||||||
cache: false
|
cache: false
|
||||||
|
|||||||
2
.github/workflows/goreleaser.yml
vendored
2
.github/workflows/goreleaser.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: "^1"
|
go-version: "^1"
|
||||||
- name: Run GoReleaser
|
- name: Run GoReleaser
|
||||||
|
|||||||
19
context.go
19
context.go
@ -654,14 +654,23 @@ func (c *Context) GetPostFormMap(key string) (map[string]string, bool) {
|
|||||||
func getMapFromFormData(m map[string][]string, key string) (map[string]string, bool) {
|
func getMapFromFormData(m map[string][]string, key string) (map[string]string, bool) {
|
||||||
d := make(map[string]string)
|
d := make(map[string]string)
|
||||||
found := false
|
found := false
|
||||||
|
keyLen := len(key)
|
||||||
|
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
if i := strings.IndexByte(k, '['); i >= 1 && k[0:i] == key {
|
if len(k) < keyLen+3 { // key + "[" + at least one char + "]"
|
||||||
if j := strings.IndexByte(k[i+1:], ']'); j >= 1 {
|
continue
|
||||||
found = true
|
}
|
||||||
d[k[i+1:][:j]] = v[0]
|
|
||||||
}
|
if k[:keyLen] != key || k[keyLen] != '[' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if j := strings.IndexByte(k[keyLen+1:], ']'); j > 0 {
|
||||||
|
found = true
|
||||||
|
d[k[keyLen+1:keyLen+1+j]] = v[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return d, found
|
return d, found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3554,3 +3554,88 @@ func TestGetMapFromFormData(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkGetMapFromFormData(b *testing.B) {
|
||||||
|
// Test case 1: Small dataset with bracket notation
|
||||||
|
smallData := map[string][]string{
|
||||||
|
"ids[a]": {"hi"},
|
||||||
|
"ids[b]": {"3.14"},
|
||||||
|
"names[a]": {"mike"},
|
||||||
|
"names[b]": {"maria"},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test case 2: Medium dataset with mixed data
|
||||||
|
mediumData := map[string][]string{
|
||||||
|
"ids[a]": {"hi"},
|
||||||
|
"ids[b]": {"3.14"},
|
||||||
|
"ids[c]": {"test"},
|
||||||
|
"ids[d]": {"value"},
|
||||||
|
"names[a]": {"mike"},
|
||||||
|
"names[b]": {"maria"},
|
||||||
|
"names[c]": {"john"},
|
||||||
|
"names[d]": {"jane"},
|
||||||
|
"other[key1]": {"value1"},
|
||||||
|
"other[key2]": {"value2"},
|
||||||
|
"simple": {"data"},
|
||||||
|
"another": {"info"},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test case 3: Large dataset with many bracket keys
|
||||||
|
largeData := make(map[string][]string)
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
key := fmt.Sprintf("ids[%d]", i)
|
||||||
|
largeData[key] = []string{fmt.Sprintf("value%d", i)}
|
||||||
|
}
|
||||||
|
for i := 0; i < 50; i++ {
|
||||||
|
key := fmt.Sprintf("names[%d]", i)
|
||||||
|
largeData[key] = []string{fmt.Sprintf("name%d", i)}
|
||||||
|
}
|
||||||
|
for i := 0; i < 25; i++ {
|
||||||
|
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++ {
|
||||||
|
key := fmt.Sprintf("nonmatching%d", i)
|
||||||
|
worstCaseData[key] = []string{fmt.Sprintf("value%d", i)}
|
||||||
|
}
|
||||||
|
worstCaseData["ids[a]"] = []string{"hi"}
|
||||||
|
worstCaseData["ids[b]"] = []string{"3.14"}
|
||||||
|
|
||||||
|
// Test case 5: Dataset with short keys (best case for early exit)
|
||||||
|
shortKeysData := map[string][]string{
|
||||||
|
"a": {"value1"},
|
||||||
|
"b": {"value2"},
|
||||||
|
"ids[a]": {"hi"},
|
||||||
|
"ids[b]": {"3.14"},
|
||||||
|
}
|
||||||
|
|
||||||
|
benchmarks := []struct {
|
||||||
|
name string
|
||||||
|
data map[string][]string
|
||||||
|
key string
|
||||||
|
}{
|
||||||
|
{"Small_Bracket", smallData, "ids"},
|
||||||
|
{"Small_Names", smallData, "names"},
|
||||||
|
{"Medium_Bracket", mediumData, "ids"},
|
||||||
|
{"Medium_Names", mediumData, "names"},
|
||||||
|
{"Medium_Other", mediumData, "other"},
|
||||||
|
{"Large_Bracket", largeData, "ids"},
|
||||||
|
{"Large_Names", largeData, "names"},
|
||||||
|
{"Large_Other", largeData, "other"},
|
||||||
|
{"WorstCase_Bracket", worstCaseData, "ids"},
|
||||||
|
{"ShortKeys_Bracket", shortKeysData, "ids"},
|
||||||
|
{"Empty_Key", smallData, "notfound"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, bm := range benchmarks {
|
||||||
|
b.Run(bm.name, func(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, _ = getMapFromFormData(bm.data, bm.key)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
4
go.mod
4
go.mod
@ -13,10 +13,10 @@ require (
|
|||||||
github.com/modern-go/reflect2 v1.0.2
|
github.com/modern-go/reflect2 v1.0.2
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4
|
github.com/pelletier/go-toml/v2 v2.2.4
|
||||||
github.com/quic-go/quic-go v0.54.0
|
github.com/quic-go/quic-go v0.54.0
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.11.1
|
||||||
github.com/ugorji/go/codec v1.3.0
|
github.com/ugorji/go/codec v1.3.0
|
||||||
golang.org/x/net v0.42.0
|
golang.org/x/net v0.42.0
|
||||||
google.golang.org/protobuf v1.36.6
|
google.golang.org/protobuf v1.36.8
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|||||||
8
go.sum
8
go.sum
@ -57,8 +57,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
||||||
@ -82,8 +82,8 @@ golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
|||||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user