Repository: gin-gonic/gin
Pull request #4304 (2025-07-19 09:32:30)

refactor(context): remove unused Context dependency in get method
- The `get` method on `Context` did not use its receiver `c`, making it misleading.
- Renamed `get` to `getMapFromFormData` and made it a standalone function.




Patch:
diff --git a/context.go b/context.go
index b184678..cb3362f 100644
--- a/context.go
+++ b/context.go
@@ -573,7 +573,7 @@ func (c *Context) QueryMap(key string) (dicts map[string]string) {
 // whether at least one value exists for the given key.
 func (c *Context) GetQueryMap(key string) (map[string]string, bool) {
 	c.initQueryCache()
-	return c.get(c.queryCache, key)
+	return getMapFromFormData(c.queryCache, key)
 }
 
 // PostForm returns the specified key from a POST urlencoded form or multipart form
@@ -646,22 +646,23 @@ func (c *Context) PostFormMap(key string) (dicts map[string]string) {
 // whether at least one value exists for the given key.
 func (c *Context) GetPostFormMap(key string) (map[string]string, bool) {
 	c.initFormCache()
-	return c.get(c.formCache, key)
+	return getMapFromFormData(c.formCache, key)
 }
 
-// get is an internal method and returns a map which satisfies conditions.
-func (c *Context) get(m map[string][]string, key string) (map[string]string, bool) {
-	dicts := make(map[string]string)
-	exist := false
+// getMapFromFormData return a map which satisfies conditions.
+// It parses from data with bracket notation like "key[subkey]=value" into a map.
+func getMapFromFormData(m map[string][]string, key string) (map[string]string, bool) {
+	d := make(map[string]string)
+	found := false
 	for k, v := range m {
 		if i := strings.IndexByte(k, '['); i >= 1 && k[0:i] == key {
 			if j := strings.IndexByte(k[i+1:], ']'); j >= 1 {
-				exist = true
-				dicts[k[i+1:][:j]] = v[0]
+				found = true
+				d[k[i+1:][:j]] = v[0]
 			}
 		}
 	}
-	return dicts, exist
+	return d, found
 }
 
 // FormFile returns the first file for the provided form key.


Test patch:
diff --git a/context_test.go b/context_test.go
index 74f0842..895cd8a 100644
--- a/context_test.go
+++ b/context_test.go
@@ -3350,3 +3350,134 @@ func TestContextSetCookieData(t *testing.T) {
 		assert.Contains(t, setCookie, "SameSite=None")
 	})
 }
+
+func TestGetMapFromFormData(t *testing.T) {
+	testCases := []struct {
+		name     string
+		data     map[string][]string
+		key      string
+		expected map[string]string
+		found    bool
+	}{
+		{
+			name: "Basic bracket notation",
+			data: map[string][]string{
+				"ids[a]": {"hi"},
+				"ids[b]": {"3.14"},
+			},
+			key: "ids",
+			expected: map[string]string{
+				"a": "hi",
+				"b": "3.14",
+			},
+			found: true,
+		},
+		{
+			name: "Mixed data with bracket notation",
+			data: map[string][]string{
+				"ids[a]":     {"hi"},
+				"ids[b]":     {"3.14"},
+				"names[a]":   {"mike"},
+				"names[b]":   {"maria"},
+				"other[key]": {"value"},
+				"simple":     {"data"},
+			},
+			key: "ids",
+			expected: map[string]string{
+				"a": "hi",
+				"b": "3.14",
+			},
+			found: true,
+		},
+		{
+			name: "Names key",
+			data: map[string][]string{
+				"ids[a]":     {"hi"},
+				"ids[b]":     {"3.14"},
+				"names[a]":   {"mike"},
+				"names[b]":   {"maria"},
+				"other[key]": {"value"},
+			},
+			key: "names",
+			expected: map[string]string{
+				"a": "mike",
+				"b": "maria",
+			},
+			found: true,
+		},
+		{
+			name: "Key not found",
+			data: map[string][]string{
+				"ids[a]":   {"hi"},
+				"names[b]": {"maria"},
+			},
+			key:      "notfound",
+			expected: map[string]string{},
+			found:    false,
+		},
+		{
+			name:     "Empty data",
+			data:     map[string][]string{},
+			key:      "ids",
+			expected: map[string]string{},
+			found:    false,
+		},
+		{
+			name: "Malformed bracket notation",
+			data: map[string][]string{
+				"ids[a": {"hi"},    // Missing closing bracket
+				"ids]b": {"3.14"},  // Missing opening bracket
+				"idsab": {"value"}, // No brackets
+			},
+			key:      "ids",
+			expected: map[string]string{},
+			found:    false,
+		},
+		{
+			name: "Nested bracket notation",
+			data: map[string][]string{
+				"ids[a][b]": {"nested"},
+				"ids[c]":    {"simple"},
+			},
+			key: "ids",
+			expected: map[string]string{
+				"a": "nested",
+				"c": "simple",
+			},
+			found: true,
+		},
+		{
+			name: "Simple key without brackets",
+			data: map[string][]string{
+				"simple": {"data"},
+				"ids[a]": {"hi"},
+			},
+			key:      "simple",
+			expected: map[string]string{},
+			found:    false,
+		},
+		{
+			name: "Mixed simple and bracket keys",
+			data: map[string][]string{
+				"simple": {"data"},
+				"ids[a]": {"hi"},
+				"ids[b]": {"3.14"},
+				"other":  {"value"},
+			},
+			key: "ids",
+			expected: map[string]string{
+				"a": "hi",
+				"b": "3.14",
+			},
+			found: true,
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			result, found := getMapFromFormData(tc.data, tc.key)
+			assert.Equal(t, tc.expected, result, "result mismatch")
+			assert.Equal(t, tc.found, found, "found mismatch")
+		})
+	}
+}