2. Gin框架入门:安装、路由与请求响应处理
Gin 是 Go 语言生态中最流行的 Web 框架之一,以高性能、轻量级和极简 API 著称。本章将带你完成 Gin 的安装、项目初始化,并掌握核心的路由定义与请求响应处理方式,为后续构建 RESTful 服务打下基础。
2.1 安装与项目初始化
Gin 要求 Go 1.13 及以上版本。确保已正确设置 GOPATH 或使用 Go Modules 管理依赖。
2.1.1 创建项目并初始化模块
mkdir gin-demo && cd gin-demo
go mod init gin-demo
2.1.2 安装 Gin 框架
go get -u github.com/gin-gonic/gin
安装完成后,go.mod 文件会自动记录依赖版本。验证安装:
package main
import "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() // 默认监听 0.0.0.0:8080
}
运行 go run main.go,访问 http://localhost:8080/ping 应返回 {"message":"pong"}。
提示:
gin.Default() 默认包含 Logger 和 Recovery 中间件,适合开发阶段快速启动。生产环境可改用 gin.New() 自行组合中间件。
2.2 路由定义:GET / POST / PUT / DELETE
Gin 的路由基于 Radix Tree 实现,支持精确匹配、参数路由和通配符。以下表格列出最常用的 HTTP 方法及其对应路由注册方式:
| HTTP 方法 | Gin 路由方法 | 典型用途 | 示例路径 |
|---|---|---|---|
| GET | r.GET() |
获取资源 | /users |
| POST | r.POST() |
创建资源 | /users |
| PUT | r.PUT() |
全量更新资源 | /users/:id |
| DELETE | r.DELETE() |
删除资源 | /users/:id |
2.2.1 完整路由示例
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// GET:查询用户列表
r.GET("/users", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"method": "GET", "path": "/users"})
})
// POST:创建新用户
r.POST("/users", func(c *gin.Context) {
c.JSON(http.StatusCreated, gin.H{"method": "POST", "path": "/users"})
})
// PUT:更新指定用户(:id 为路径参数)
r.PUT("/users/:id", func(c *gin.Context) {
id := c.Param("id")
c.JSON(http.StatusOK, gin.H{"method": "PUT", "path": "/users/" + id})
})
// DELETE:删除指定用户
r.DELETE("/users/:id", func(c *gin.Context) {
id := c.Param("id")
c.JSON(http.StatusOK, gin.H{"method": "DELETE", "path": "/users/" + id})
})
r.Run(":8080")
}
2.2.2 路径参数与查询参数
- 路径参数:使用
:param语法,通过c.Param("param")获取。 - 查询参数:通过
c.Query("key")或c.DefaultQuery("key", "default")获取。
// 示例:GET /users/123?page=2&size=20
r.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
page := c.DefaultQuery("page", "1")
size := c.DefaultQuery("size", "10")
c.JSON(http.StatusOK, gin.H{
"id": id,
"page": page,
"size": size,
})
})
注意: 路径参数和查询参数名称区分大小写。建议统一使用小写字母加下划线风格(snake_case)。
2.3 处理请求与响应
Gin 的 Context 对象封装了请求的读取和响应的写入。以下是最常用的请求数据绑定与响应格式。
2.3.1 请求数据绑定
Gin 支持自动将 JSON、表单、查询参数绑定到结构体:
type User struct {
Name string `json:"name" form:"name" binding:"required"`
Email string `json:"email" form:"email" binding:"required,email"`
Age int `json:"age" form:"age" binding:"gte=0,lte=150"`
}
r.POST("/users", func(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, gin.H{"user": user})
})
2.3.2 响应格式
| 响应类型 | Gin 方法 | 说明 |
|---|---|---|
| JSON | c.JSON(code, obj) |
最常用,自动设置 Content-Type: application/json |
| XML | c.XML(code, obj) |
返回 XML 格式数据 |
| YAML | c.YAML(code, obj) |
返回 YAML 格式数据 |
| String | c.String(code, format, values...) |
返回纯文本 |
| HTML | c.HTML(code, name, obj) |
渲染模板文件 |
| File | c.File(filepath) |
返回文件下载 |
2.3.3 统一响应结构
为便于前端解析和后端维护,建议定义统一的响应结构:
type Response struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
func Success(c *gin.Context, data interface{}) {
c.JSON(http.StatusOK, Response{
Code: 0,
Message: "success",
Data: data,
})
}
func Error(c *gin.Context, httpCode int, message string) {
c.JSON(httpCode, Response{
Code: httpCode,
Message: message,
})
}
2.4 Gin 请求处理流程
下图展示了 Gin 从接收 HTTP 请求到返回响应的完整内部流程:
2.5 路由分组与模块化
当路由数量增多时,使用 Group 进行模块化管理:
func main() {
r := gin.Default()
// 用户相关路由组
userGroup := r.Group("/users")
{
userGroup.GET("", listUsers)
userGroup.POST("", createUser)
userGroup.GET("/:id", getUser)
userGroup.PUT("/:id", updateUser)
userGroup.DELETE("/:id", deleteUser)
}
// 订单相关路由组
orderGroup := r.Group("/orders")
{
orderGroup.GET("", listOrders)
orderGroup.POST("", createOrder)
}
r.Run(":8080")
}
最佳实践: 将路由分组与版本号结合,例如
/api/v1/users,便于 API 版本演进。同时将每个资源的路由定义拆分到独立文件,保持 main.go 简洁。
2.6 本章小结
通过本章学习,你已掌握:
- Gin 框架的安装与项目初始化流程
- GET / POST / PUT / DELETE 四种核心路由的定义方式
- 路径参数与查询参数的获取方法
- 请求数据绑定与多种响应格式的使用
- 路由分组实现模块化组织