# 第 3 章 Gin 入门 > 学完本章你将:理解 Gin 的定位与优势、跑通第一个 Gin 服务、看懂 Gin 与标准库 net/http 的关系。 ## 3.1 为什么选 Gin - **快**:基于 httprouter 的前缀树路由,性能居 Go Web 框架前列 - **简洁**:`gin.Default()` 一行起服务,`c.JSON` 一行返回 - **生态**:中间件、绑定、验证、分组等开箱即用 - **本项目已选型**:`go.mod` 中 `github.com/gin-gonic/gin v1.12.0` 对比: | 方案 | 特点 | 适合 | |------|------|------| | `net/http` | 标准库,无依赖,可控 | 小服务、学习 | | Gin | 高性能、API 友好 | RESTful API、中大型项目 | | Echo/Fiber | 类似 Gin,Fiber 基于 fasthttp | 追求极致性能或特定风格 | ## 3.2 安装与初始化 本项目已初始化,可直接 `make tidy`。从零新建: ```bash mkdir myapp && cd myapp go mod init myapp go get github.com/gin-gonic/gin ``` ## 3.3 Hello World ```go package main import "github.com/gin-gonic/gin" func main() { r := gin.Default() // 含 Logger + Recovery 中间件 r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{"message": "pong"}) }) r.Run(":8080") // 监听 0.0.0.0:8080 } ``` 运行 `go run main.go`,访问 `http://localhost:8080/ping`。 - `gin.H` 是 `map[string]any` 的别名,方便构造 JSON - `c.JSON(code, obj)` 自动设置 `Content-Type: application/json` ## 3.4 Gin 与 net/http 的关系 Gin 不是另起炉灶,而是对 `net/http` 的封装: ```go // Gin 实现了 http.Handler 接口,所以可直接给 http.Server srv := &http.Server{ Addr: ":8080", Handler: r, // r 是 *gin.Engine,实现了 ServeHTTP } srv.ListenAndServe() ``` 本项目 `cmd/server/main.go` 正是这种写法,以便支持优雅关闭(`srv.Shutdown`)。若用 `r.Run()` 则无法优雅关闭,仅适合 demo。 `gin.Context` 包装了 `http.Request` 与 `http.ResponseWriter`,提供 `Param`/`Query`/`Bind`/`JSON` 等快捷方法。 ## 3.5 gin.Default() vs gin.New() ```go // Default 自带 Logger + Recovery r := gin.Default() // New 空引擎,需手动注册(本项目采用,便于替换为 Zap) r := gin.New() r.Use(middleware.Recovery()) r.Use(middleware.ZapLogger()) ``` 本项目 `internal/router/router.go` 使用 `gin.New()` 并注册自定义 Zap 日志与 Recovery,生产更可控。 ## 3.6 运行模式 ```go gin.SetMode(gin.DebugMode) // 开发:详细日志 gin.SetMode(gin.ReleaseMode) // 生产:精简日志 gin.SetMode(gin.TestMode) // 测试 ``` 本项目由 `config.yaml` 的 `server.mode` 控制,在 `router.New` 中 `gin.SetMode(cfg.Server.Mode)`。 ## 3.7 项目初始化对照 本项目入口 `cmd/server/main.go` 关键步骤: 1. `config.Load()` 加载配置 2. `logger.Init` 初始化 Zap 3. `router.New(cfg)` 创建 Gin 引擎 4. `http.Server` + goroutine 启动 5. `signal.Notify` 等待退出信号,`srv.Shutdown` 优雅关闭 这是生产级 Gin 服务的标准启动模板,建议熟记。 ## 3.8 动手练习 1. 用 `gin.Default()` 写一个返回当前时间的 `/time` 接口。 2. 改为 `gin.New()` + 自定义 Logger,观察差异。 3. 将启动方式从 `r.Run` 改为 `http.Server` + 优雅关闭。