上线前必须执行安全检查:强制https与hsts、禁用debug模式、结构体绑定校验输入、严格校验文件上传、正确使用context取消机制。

上线前不跑一遍安全检查,等于把钥匙塞进日志里再发到生产环境。
HTTP 服务是否强制启用 HTTPS 与 HSTS
Gin 默认用 http.ListenAndServe 启动明文 HTTP,哪怕反向代理(如 Nginx)配了 HTTPS,内部流量仍可能被中间人劫持。必须显式禁用 HTTP 或重定向。
- 线上环境禁止调用
r.Run(),改用http.ListenAndServeTLS并提供有效证书;若用反代,至少在 Gin 中加中间件强制跳转:c.Redirect(http.StatusMovedPermanently, "https://"+c.Request.Host+c.Request.RequestURI) - 通过
Header("Strict-Transport-Security", "max-age=31536000; includeSubDomains")设置 HSTS,防止首次请求被降级 - 检查
GO_ENV或配置项是否误设为debug,避免泄露gin.DebugPrintRouteFunc路由表
用户输入是否全部走结构体绑定 + validator 校验
手写 c.Query/c.PostForm 取值再 if 判断,极易漏掉边界或类型转换错误,且无法统一拦截 XSS/SQLi 风险。
- 所有 API 入参必须定义 struct,并用
binding标签声明规则,例如:Username string `json:"username" binding:"required,min=3,max=20,alphanum"` - 禁用
binding:"-"或binding:"optional"这类模糊标签,字段存在性、空值、零值都应明确校验逻辑 - 自定义验证器(如手机号、身份证)必须注册到全局 validator 实例,而非每次新建 —— 否则
binding不生效 - 校验失败时,直接用
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid input"}),不要继续执行业务逻辑
文件上传是否校验 *multipart.FileHeader 而非 multipart.File
c.FormFile("avatar") 返回的 multipart.File 是接口类型,即使前端没传文件,它也可能非 nil,直接 if file == nil 判空会失效,后续 file.Size 或 io.Copy panic。
- 正确方式是检查第二个返回值:
_, header, err := c.Request.FormFile("avatar"),if header == nil才表示未上传 - 必须限制
header.Size(如),并在 <code>c.Request.ParseMultipartForm前调用c.Request.MultipartReader()防止内存爆涨 - 文件名必须用
path.Base(header.Filename)截取,禁用原始header.Filename,否则路径遍历(../../../etc/passwd)可写任意位置
Context 是否在每个 handler 入口配对 cancel,且 defer 在 goroutine 外
漏掉 cancel() 是 goroutine 泄漏最常见原因,而把 defer cancel() 写在 goroutine 里等于没写。
- 每个
http.HandlerFunc开头必须有:ctx, cancel := context.WithTimeout(c.Request.Context(), 5*time.Second),并在函数末尾defer cancel() - 若 handler 内启新 goroutine(如异步发消息),需传入
ctx,但cancel()必须在原 handler 作用域内 defer,不能放到 goroutine 里 - 检查所有
context.WithValue使用:仅用于传递请求元数据(如 user.ID),禁止传业务对象或 channel —— 容易导致内存泄漏
真正卡住上线的不是语法错误,而是 context 没 cancel、error 没 %w 包装、FileHeader 判空错位、以及 validator 规则漏覆盖字段 —— 这四点,比任何 lint 工具都管用。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











