4.6 KiB
4.6 KiB
tags, create time
| tags | create time | |||||
|---|---|---|---|---|---|---|
|
2026-06-07 15:20 |
Gin
概述
Gin 是 Go 生态中最流行的 Web 框架,以高性能路由和简洁的 API 著称。本文从基础用法到中间件、分组路由,覆盖构建 RESTful API 的核心技能。
正文
安装
go get -u github.com/gin-gonic/gin
快速开始
[!question] 💭 思考 如果让你从零实现一个 HTTP 服务器,需要处理哪些事情?(路由匹配、请求解析、响应格式化……)
Gin 封装了这些底层细节,让你专注于业务逻辑:
r := gin.Default() // 创建默认引擎(含 Logger + Recovery 中间件)
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong"})
})
r.Run(":8080") // 监听 8080 端口
[!tip] 💡 Default vs New
gin.New():纯引擎,无日志和恢复中间件gin.Default():预装 Logger 和 Recovery,生产环境推荐- Recovery 中间件会自动 recover panic,避免服务崩溃
路由与参数
路径参数
r.GET("/user/:name", func(c *gin.Context) {
name := c.Param("name") // 获取 :name 的值
c.String(200, "Hello %s", name)
})
Query 参数
r.GET("/search", func(c *gin.Context) {
q := c.Query("q", "") // 获取 ?q=xxx,默认值 ""
page := c.DefaultQuery("page", "1") // 带默认值
c.JSON(200, gin.H{"query": q, "page": page})
})
POST 表单 / JSON
type LoginRequest struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
r.POST("/login", func(c *gin.Context) {
var req LoginRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
// 处理登录...
c.JSON(200, gin.H{"message": "ok"})
})
[!warning] ⚠️ 绑定注意事项
ShouldBindJSON仅在 Content-Type 为application/json时生效binding:"required"由内置验证器检查字段是否为空- 对于复杂验证需求,建议使用
github.com/go-playground/validator
中间件
[!question] 💭 思考 如果你的 API 需要对所有请求做日志记录、鉴权、CORS 处理,在每个 handler 里重复写代码合理吗?
中间件是横切关注点的标准解决方案——它在请求到达 handler 之前和返回响应之后执行:
// 自定义中间件
func RequestID() gin.HandlerFunc {
return func(c *gin.Context) {
id := uuid.New().String()
c.Set("requestID", id) // 存入上下文
c.Header("X-Request-ID", id)
c.Next() // ✅ 必须调用,继续处理后续中间件/handler
// 这里可以记录耗时等后处理逻辑
}
}
// 注册方式
r.Use(RequestID()) // 全局中间件
r.GET("/api", MyHandler) // 受中间件保护
[!info] ℹ️ 中间件执行顺序 先注册的先执行(类似洋葱模型):
请求 → Logger → Auth → CORS → Handler 响应 ← Logger ← Auth ← CORS ← Handler
分组路由
v1 := r.Group("/api/v1")
{
v1.GET("/users", getUsers)
v1.POST("/users", createUser)
v1.PUT("/users/:id", updateUser)
v1.DELETE("/users/:id", deleteUser)
}
// 为组注册中间件
authGroup := r.Group("/api", AuthMiddleware())
RESTful 完整示例
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Age int `json:"age"`
}
var users []User
func main() {
r := gin.Default()
r.GET("/users", func(c *gin.Context) {
c.JSON(200, users)
})
r.GET("/users/:id", func(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
for _, u := range users {
if u.ID == id {
c.JSON(200, u)
return
}
}
c.JSON(404, gin.H{"error": "not found"})
})
r.POST("/users", func(c *gin.Context) {
var u User
c.ShouldBindJSON(&u)
u.ID = len(users) + 1
users = append(users, u)
c.JSON(201, u)
})
r.Run(":8080")
}
[!tip] 💡 性能提示
gin.H是map[string]interface{}的别名,在高频场景中考虑使用自定义结构体替代,减少反射开销- 启用 Gzip 压缩:
r.Use(gzip.Gzip(gzip.DefaultCompression))- 生产环境建议关闭 Debug 模式:
gin.SetMode(gin.ReleaseMode)
关联笔记
- hzh/GolangStar/Go语言框架/gorm — Gin + GORM 是全栈开发的经典组合
- hzh/GolangStar/Go语言进阶/Context — HTTP 请求天然适合用 context 控制超时和取消