Gin - 获取 POST 请求参数

获取 POST 参数

在 Gin 中,POST 请求的 Body 可以包含多种格式,不同格式对应不同的读取方式。常见的包括:

  • application/x-www-form-urlencoded(form 表单)
  • multipart/form-data(文件上传)
  • application/json(JSON)
  • 原始字节流(raw body)

读取 form body

当请求使用 application/x-www-form-urlencoded 发送数据时,可以通过 c.PostForm 获取 form 表单中的字段。

注意:
c.PostForm 只适用于 form 表单类型的请求,不适用于 application/json 类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"io"

"github.com/gin-gonic/gin"
)

func main() {
r := gin.Default()

r.POST("/form-body", func(c *gin.Context) {
name := c.PostForm("name")
age := c.PostForm("age")
c.JSON(200, gin.H{
"name": name,
"age": age,
})
})

r.Run()
}

请求示例:

Gin - 获取 POST 请求参数

读取 form body 并设置默认值

和 GET 请求中的 Query 类似,POST form 也支持默认值。

1
2
name := c.DefaultPostForm("name", "default-name")
age := c.DefaultPostForm("age", "default-age")

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"io"

"github.com/gin-gonic/gin"
)

func main() {
r := gin.Default()

r.POST("/form-default-body", func(c *gin.Context) {
name := c.DefaultPostForm("name", "default-name")
age := c.DefaultPostForm("age", "default-age")
c.JSON(200, gin.H{
"name": name,
"age": age,
})
})

r.Run()
}

请求示例:

Gin - 获取 POST 请求参数

直接读取字节流(Raw Body)

在 Gin 中,c.Request.Body 实质上是一个 io.ReadCloser,底层是字节流。对于 application/json(或任何非 form 类型)请求,你可以直接手动读取原始 body:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import (
"bytes"
"io"

"github.com/gin-gonic/gin"
)

func main() {
r := gin.Default()

r.POST("/raw-body", func(c *gin.Context) {
body, err := io.ReadAll(c.Request.Body)
if err != nil {
c.JSON(500, gin.H{
"message": "Internal Server Error",
})
c.Abort()
return
}
defer c.Request.Body.Close()

c.JSON(200, gin.H{
"body": string(body),
})
})

r.Run()
}

请求示例:

Gin - 获取 POST 请求参数

说明:

  • 通过 io.ReadAll 读取后,body 会被“消耗”掉,后续再读取时将为空。
  • 读取到的 body 是 []byte,需要 string(body) 才能看到内容。

回写字节流(让 body 可再次读取)

如前所述,io.ReadAll 读取 body 后,body 的内容会被清空,因此你无法在读取 raw body 后再继续使用 PostForm 读取字段。

示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
r.POST("/raw-body2", func(c *gin.Context) {
body, err := io.ReadAll(c.Request.Body)
if err != nil {
c.JSON(500, gin.H{
"message": "Internal Server Error",
})
c.Abort()
return
}

// 读取不到 name 和 age
name := c.PostForm("name")
age := c.PostForm("age")

defer c.Request.Body.Close()
c.JSON(200, gin.H{
"name": name,
"age": age,
"body": string(body),
})
})

请求示例:

Gin - 获取 POST 请求参数

解决方法:回写字节流

通过 io.NopCloser + bytes.NewBuffer(body) 可以将 body“塞回去”,让后续代码可以继续读取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
r.POST("/raw-body3", func(c *gin.Context) {
body, err := io.ReadAll(c.Request.Body)
if err != nil {
c.JSON(500, gin.H{
"message": "Internal Server Error",
})
c.Abort()
return
}

// 回写 字节流
c.Request.Body = io.NopCloser(bytes.NewBuffer(body))

// 此时 PostForm 可以重新工作
name := c.PostForm("name")
age := c.PostForm("age")

defer c.Request.Body.Close()
c.JSON(200, gin.H{
"name": name,
"age": age,
"body": string(body),
})
})

请求示例:

Gin - 获取 POST 请求参数


Gin - 获取 POST 请求参数
https://blog.pangcy.cn/2025/11/20/后端编程相关/go/gin/Gin - 获取 POST 请求参数/
作者
子洋
发布于
2025年11月20日
许可协议