109 lines
3.2 KiB
Markdown
109 lines
3.2 KiB
Markdown
# 第 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` + 优雅关闭。
|