GoClub Pro

Go-gin

最近更新:2026-10-24
本页由同名 OneNote 笔记转换而来,可直接在线阅读;原始笔记文件见「Go语言相关笔记」页的原始链接。
  1. gin.Context 的 Get / Set / GetString / GetInt
  2. 用途:在同一次请求的处理流程中,跨中间件或处理函数传递数据(键值对)。
  3. Set(key string, value interface{})
  4. Get(key string) (value interface{}, exists bool)
  5. 便利方法:GetString(key), GetInt(key), GetBool(key) 等 — 这些从内部类型断言并返回零值或默认。
  6. 注意:这些键值对仅在当前请求上下文生存周期内有效,且 gin.Context 不是并发安全的(不要在未同步情况下跨 goroutine 读写 Context)。

 

 

// language: go

c.Set("userID", 123)

if v, ok := c.Get("userID"); ok {

uid := v.(int)

// use uid

}

uidStr := c.GetString("userID") // 若不是 string,会返回 ""(空串)

  1. 请求绑定(binding)与 ShouldBindJSON / BindJSON 的差别
  2. ShouldBindJSON(obj interface{}) error
    • 根据 JSON body 将请求体绑定到 obj,并返回 error;不会自动写入响应或结束请求(调用者需自己处理错误)。
  3. BindJSON(obj interface{}) error
    • 和 ShouldBindJSON 功能相同,但当绑定出错时,Gin 会自动写一个 400 响应并结束请求处理(内部会调用 c.ShouldBindWith 并在失败时 AbortWithError)。因此 Bind* 通常用于快速示例,但不够灵活。
  4. ShouldBind(obj interface{})
    • 根据 Content-Type 自动选择绑定器(JSON、form、xml 等)。
  5. ShouldBindQuery(obj interface{})
    • 仅绑定 Query 参数(URL ?a=b&c=d)。
  6. 关键规则:ShouldBindXxx 返回错误但不写响应;BindXxx 在出错时会自动写 400 并 abort(注意版本差异,建议以 ShouldBindXxx + 自己处理为主)。

常见绑定标签:

  • json:"fieldname" — 用于 JSON 编码/解码;
  • form:"fieldname" — 用于表单 / query 绑定;
  • binding:"required" — 强制字段必须存在(validator.v10 生效);
  • 其它 validator 标签:min,max,email,oneof,len,uuid 等。
  • c.Get / c.Set:是对 gin.Context 的键值存取,属于“上下文内存”——用于中间件与处理器之间传递数据(例如认证中间件把 userID 放进去)。它不从 HTTP 请求体里解析数据。
  • c.ShouldBind / c.ShouldBindJSON / c.ShouldBindQuery / c.ShouldBindUri 等:是“从 HTTP 请求中解析(绑定)数据到结构体”的方法。它们从请求的不同位置(body、query、form、path)读取数据并做可选验证。
    两者用途完全不同:一个是上下文内临时存储,一个是把请求数据解析到结构体中
  1. 文件上传:FormFile / SaveUploadedFile / 流式处理
  2. c.FormFile("file") (*multipart.FileHeader, error)
    • 获取一个上传文件的 FileHeader(单文件)。通常来源于 multipart/form-data 表单。
  3. c.SaveUploadedFile(fileHeader, dst) error
    • 便捷保存文件到目标路径(内部会打开文件并复制)。
  4. 打开并流式读取:
    • fh, _ := c.FormFile("file")
    • src, err := fh.Open() // 返回 multipart.File (实现 io.Reader)
    • 然后可 stream 到磁盘、云存储、或进行处理。
  5. MaxMultipartMemory
    • Gin 默认 router.MaxMultipartMemory = 32 << 20 // 32 MiB
    • 超过此内存限制,文件会被存成临时文件(仍可上传),但为了限制整体接收大小,可以在路由层或 net/http 层使用 http.MaxBytesReader。

    // language: go

    func uploadHandler(c *gin.Context) {

    // 限制请求体大小(保护)

    c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 10<<20) // 10MB

     

    fh, err := c.FormFile("file")

    if err != nil {

    c.JSON(http.StatusBadRequest, gin.H{"error": "file required"})

    return

    }

    // 简单检查 mime (不要完全相信客户端)

    if fh.Size > 5<<20 { // 5MB

    c.JSON(http.StatusBadRequest, gin.H{"error": "file too large"})

    return

    }

    dst := path.Join("/tmp", fh.Filename)

    if err := c.SaveUploadedFile(fh, dst); err != nil {

    c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})

    return

    }

    c.JSON(http.StatusOK, gin.H{"status": "uploaded", "path": dst})

    }

    注意点:

    • FormFile 只是将数据解析为 FileHeader,它本身不检查业务限制(size、type),需要手动检查。
    • 文件名不能直接信任:避免目录遍历、使用安全的文件名或随机名。
    • 如果想把文件直接上传到云存储(S3/OSS),使用 fh.Open() 取得 io.Reader,然后将数据流式传到云 SDK,避免在本地完整保存

     

  1. GetRawData 与 一次性读取 body
  2. c.GetRawData() 返回请求体的全部字节,但注意:请求体在被读取一次后就被耗尽(io.ReadCloser)。
  3. 如果你需要在中间件读取 body 并在下游处理器再绑定,需要把 body 重新塞回去:

// language: go

data, _ := c.GetRawData()

c.Request.Body = io.NopCloser(bytes.NewBuffer(data))

// 现在下游可以再读取

  1. body 被读取一次的问题与恢复
    如果你在中间件读取了 body(比如记录日志),下游的 ShouldBindJSON 就会失败(body 已读尽)。恢复方法:

// language: go

data, _ := c.GetRawData()

// 做日志等

c.Request.Body = io.NopCloser(bytes.NewBuffer(data))

// 现在下游可以再次读取或 ShouldBindJSON

 

 

  1. 安全与并发注意点
  2. gin.Context 不是并发安全的:不要在没有同步的情况下在多个 goroutine 中同时读写 c(例如你若要在 goroutine 中使用 c,请先复制需要的值,或使用 c.Copy())。
  3. 在接受文件或大请求体时,务必限制大小(http.MaxBytesReader + MaxMultipartMemory)以防 DDOS 或 OOM。
  4. 不信任客户端的 filename 或 content-type;对文件类型做服务器端检测(如读取文件头魔术字)。
  5. 验证器注入与用户错误信息不要暴露内部实现细节。
  1. 绑定优先级与选择
  2. c.ShouldBind 会根据请求 Content-Type 自动选择 binder(JSON、XML、form、multipart)。
  3. 如果你确定要解析 JSON,请用 ShouldBindJSON(强制 JSON)。
  4. 参数来源示例:
    • JSON body -> ShouldBindJSON
    • Query 参数 -> ShouldBindQuery
    • form (application/x-www-form-urlencoded 或 multipart/form-data) -> ShouldBindWith or ShouldBind
  5. 若在单个 handler 同时想解析多种来源(如 URL param + JSON body),分别调用对应绑定方法。
内容反馈

发现错误或想补充内容?

GoClub Pro 是静态知识库,评论功能不再加载第三方脚本。你可以在 GitHub 仓库提交 Issue,反馈会直接进入项目协作流程。

提交 GitHub 反馈