gin
gin copied to clipboard
Optimize the initFormCache method of the Context struct
Delete unnecessary initialization of the context formCache.
Below is my local test code:
context.go
func (c *Context) initFormCache() {
if c.formCache == nil {
c.formCache = make(url.Values)
req := c.Request
if err := req.ParseMultipartForm(c.engine.MaxMultipartMemory); err != nil {
if !errors.Is(err, http.ErrNotMultipart) {
debugPrint("error on parse multipart form array: %v", err)
}
}
c.formCache = req.PostForm
}
}
func (c *Context) newInitFormCache() {
if c.formCache == nil {
req := c.Request
if err := req.ParseMultipartForm(c.engine.MaxMultipartMemory); err != nil {
if !errors.Is(err, http.ErrNotMultipart) {
debugPrint("error on parse multipart form array: %v", err)
}
}
c.formCache = req.PostForm
}
}
context_test.go
func getTestInitFormCacheContext() *Context {
return &Context{
Request: &http.Request{
PostForm: url.Values{
"k0": []string{"0"},
"k1": []string{"1", "1"},
"k2": []string{},
},
},
engine: &Engine{
MaxMultipartMemory: 100,
},
}
}
// the context.Request.ParseMultipartForm method will return an error which is not http.ErrNotMultipart.
func getErrTestInitFormCacheContext() *Context {
return &Context{
Request: &http.Request{
PostForm: url.Values{
"k0": []string{"0"},
"k1": []string{"1", "1"},
"k2": []string{},
},
Header: http.Header{
"Content-Type": []string{"application/json; charset=utf-8"},
},
},
engine: &Engine{
MaxMultipartMemory: 100,
},
}
}
func TestNewIntiFormCache(t *testing.T) {
{
ctx0 := getTestInitFormCacheContext()
ctx0.initFormCache()
ctx1 := getTestInitFormCacheContext()
ctx1.newInitFormCache()
assert.Equal(t, ctx0.formCache, ctx1.formCache)
}
{
ctx0 := getTestInitFormCacheContext()
ctx0.Request.PostForm = nil
ctx0.initFormCache()
ctx1 := getTestInitFormCacheContext()
ctx1.Request.PostForm = nil
ctx1.newInitFormCache()
assert.Equal(t, ctx0.formCache, ctx1.formCache)
}
{
ctx0 := getTestInitFormCacheContext()
ctx0.Request.PostForm = make(url.Values)
ctx0.initFormCache()
ctx1 := getTestInitFormCacheContext()
ctx1.Request.PostForm = make(url.Values)
ctx1.newInitFormCache()
assert.Equal(t, ctx0.formCache, ctx1.formCache)
}
}
func TestNewIntiFormCacheWithParseMultipartFormError(t *testing.T) {
ctx0 := getErrTestInitFormCacheContext()
ctx0.initFormCache()
ctx1 := getErrTestInitFormCacheContext()
ctx1.newInitFormCache()
assert.Equal(t, ctx0.formCache, ctx1.formCache)
}
func BenchmarkInitFormCache(b *testing.B) {
ctx := getTestInitFormCacheContext()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
ctx.initFormCache()
}
}
func BenchmarkNewInitFormCache(b *testing.B) {
ctx := getTestInitFormCacheContext()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
ctx.newInitFormCache()
}
}
test output
=== RUN TestNewIntiFormCache
--- PASS: TestNewIntiFormCache (0.00s)
=== RUN TestNewIntiFormCacheWithParseMultipartFormError
--- PASS: TestNewIntiFormCacheWithParseMultipartFormError (0.00s)
PASS
Process finished with the exit code 0
benchmark output
goos: linux
goarch: amd64
pkg: github.com/gin-gonic/gin
cpu: Intel(R) Core(TM) i5-8400 CPU @ 2.80GHz
BenchmarkInitFormCache
BenchmarkInitFormCache-6 719376747 1.639 ns/op 0 B/op 0 allocs/op
BenchmarkNewInitFormCache
BenchmarkNewInitFormCache-6 721553457 1.636 ns/op 0 B/op 0 allocs/op
PASS
Process finished with the exit code 0