Gin 是 Go Web 开发首选轻量框架,因其性能优、API 简洁、中间件灵活且贴近 Go 习惯;它不隐藏 HTTP 细节,用 gin.Context 统一生命周期,兼顾开发效率与控制力。
Gin 在性能、API 设计和中间件机制上比 net/http 原生更高效,又比 echo 或 fiber 更贴近 Go 习惯——它不隐藏 HTTP 处理细节,但用 gin.Context 统一了请求/响应生命周期。你不需要为路由分组、JSON 解析、参数绑定写重复逻辑,但也不会被强约束在某套 ORM 或配置体系里。
别跳过 gin.SetMode(gin.ReleaseMode)。开发时默认是 DebugMode,会打印完整栈、自动重载(需额外装 air)、暴露敏感 header;上线前漏掉这句,等于把调试信息直接吐给生产用户。
go mod init example.com/myapp 初始化模块"github.com/gin-gonic/gin",然后写:func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong"})
})
r.Run(":8080")
}
gin.Default() 已内置日志和恢复中间件;若要完全自定义,改用 gin.New() + 手动 Use()。
一是结构体字段没加 json tag 导致解析为空;二是没检查 c.ShouldBindJSON(&v) 返回的 error 就直接用 v —— 这会导致 panic 或静默失败。
必须导出(首字母大写),且推荐显式声明 tag:type User struct { Name string `json:"name"` Age int `json:"age"` }
if err := c.ShouldBindJSON(&user); err != nil { c.AbortWithStatusJSON(400, gin.H{"error": err.Error()}); return }
ShouldBindJSON 会自动调用 json.Unmarshal 并校验 required 字段(如果用了 binding:"required")Gin 不自动查找子目录,r.Static("/static", "./static") 只服务 ./static 下的文件,不会递归进 ./static/css 或 ./static/js —— 但其实它会,只要路径匹配。真正容易踩坑的是模板:Gin 默认不支持嵌套 {{template}},且 LoadHTMLGlob 的 glob 模式必须包含完整路径,比如 r.LoadHTMLGlob("templates/**/*") 才能加载子目录下的 templates/user/index.html。
r.StaticFS("/assets", http.Dir("./assets")) 替代 Static,更可控LoadHTMLGlob 的根目录,例如 {{template "header.html" .}} 要求 header.html 在 glob 匹配范围内gin.DebugPrintRouteFunc,它会在启动时打印所有路由,可能泄露内部路径最常被忽略的是:Gin 的 c.Redirect 默认用 302,如果需要 SEO 友好或状态明确,得显式写 c.Redirect(301, "/new-path")。