Gin 基础用法
Gin 是一个基于 Go net/http 的 Web 框架,常用于创建 HTTP API。本文只介绍搭建简单服务时最常用的功能。
安装 Gin
先创建 Go 模块并安装 Gin:
go mod init example
go get github.com/gin-gonic/gin创建第一个服务
下面的程序创建了一个 Gin Engine,并注册了一个返回 JSON 的路由:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/hello", func(ctx *gin.Context) {
ctx.JSON(http.StatusOK, gin.H{
"message": "hello, Gin",
})
})
r.Run(":8080")
}运行程序后,访问 http://localhost:8080/hello,会得到:
{
"message": "hello, Gin"
}gin.Default() 会创建路由引擎,并自动添加日志和异常恢复中间件。Run() 默认启动 HTTP 服务。
注册路由
Gin 使用与 HTTP 方法同名的方法注册路由:
r.GET("/items", listItems)
r.POST("/items", createItem)
r.PUT("/items/:id", updateItem)
r.DELETE("/items/:id", deleteItem)每个处理函数都接收一个 *gin.Context:
func listItems(ctx *gin.Context) {
ctx.JSON(http.StatusOK, gin.H{
"items": []string{"book", "pen"},
})
}gin.H 构造 JSON 响应
gin.H 是 Gin 提供的 map 类型,底层与 map[string]any 等价,用来快速构造 JSON 响应。它可以存放字符串、数字、切片,甚至嵌套的 gin.H:
ctx.JSON(http.StatusOK, gin.H{
"id": 1,
"name": "book",
"tags": []string{"go", "gin"},
"author": gin.H{
"name": "Alice",
},
})返回的 JSON 是:
{
"id": 1,
"name": "book",
"tags": ["go", "gin"],
"author": {
"name": "Alice"
}
}gin.H 的 key 必须是字符串,JSON 中的字段名会按照 key 原样输出。
读取请求参数
路径参数
路由中的 :id 表示路径参数,可以使用 ctx.Param() 读取:
r.GET("/items/:id", func(ctx *gin.Context) {
id := ctx.Param("id")
ctx.JSON(http.StatusOK, gin.H{"id": id})
})访问 /items/1 时,id 的值是 "1"。
查询参数
使用 ctx.Query() 读取 URL 查询参数:
r.GET("/search", func(ctx *gin.Context) {
keyword := ctx.Query("keyword")
ctx.JSON(http.StatusOK, gin.H{"keyword": keyword})
})访问 /search?keyword=go 时,keyword 的值是 "go"。
绑定 JSON 请求体
可以将 JSON 请求体绑定到结构体,并使用 binding 标签完成基础校验:
type CreateItemRequest struct {
Name string `json:"name" binding:"required"`
}
func createItem(ctx *gin.Context) {
var request CreateItemRequest
if err := ctx.ShouldBindJSON(&request); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{
"error": "name is required",
})
return
}
ctx.JSON(http.StatusCreated, gin.H{
"name": request.Name,
})
}请求时需要设置 Content-Type: application/json:
curl -X POST http://localhost:8080/items \
-H 'Content-Type: application/json' \
-d '{"name":"book"}'ShouldBindJSON() 只返回绑定错误,不会自动生成响应,因此可以自行决定状态码和错误内容。
使用路由组
多个接口拥有相同前缀时,可以使用 Group():
api := r.Group("/api")
{
api.GET("/items", listItems)
api.POST("/items", createItem)
}上面的路由地址分别是 GET /api/items 和 POST /api/items。大括号只用于整理代码,不影响路由行为。
添加中间件
中间件可以在处理请求前后执行公共逻辑。下面的示例为响应添加一个固定的响应头:
func AddResponseHeader() gin.HandlerFunc {
return func(ctx *gin.Context) {
ctx.Header("X-App", "gin-example")
ctx.Next()
}
}
r.Use(AddResponseHeader())r.Use() 注册全局中间件,ctx.Next() 继续执行后续中间件和最终的路由处理函数。
常用响应方法
Gin 提供了多种响应方法:
ctx.JSON(http.StatusOK, gin.H{"message": "ok"})
ctx.String(http.StatusOK, "ok")
ctx.Status(http.StatusNoContent)处理函数写入响应后,如果后面还有代码,应及时 return,避免重复写入响应。
总结
Gin 的基础使用流程是:创建 Engine、注册路由、通过 gin.Context 读取请求并写入响应。掌握路径参数、查询参数、JSON 绑定、路由组和简单中间件后,就可以开始编写基础 HTTP API。