1 介绍

1.1 简介

01.Gin框架概述
    a.定义与核心
        a.框架定位
            a.高性能Go Web框架
                Gin是一个使用Go语言编写的HTTP Web框架
                专注于提供极致的性能和简洁的API
                适用于构建RESTful API和微服务
            b.技术基础
                基于httprouter路由库实现高性能路由
                采用Radix树算法进行路由匹配
                零内存分配的路由设计
            c.设计特点
                轻量级框架设计,核心代码简洁
                不包含ORM、模板引擎等重型组件
                专注于HTTP层面的功能实现
        b.开源协议
            a.MIT许可证
                完全开源免费使用
                商业友好,无使用限制
                可自由修改和分发
            b.社区支持
                GitHub上超过70k stars
                活跃的社区贡献者
                丰富的第三方扩展
    b.发展历史
        a.诞生背景
            a.2014年首次发布
                由Manu Martinez-Almeida创建
                最初是为了解决Go Web框架性能问题
                借鉴了Martini框架的API设计
            b.发展动机
                当时Go Web框架普遍性能不佳
                需要一个高性能且易用的框架
                追求极致的路由性能
        b.版本演进
            a.早期版本
                v0.x版本快速迭代
                API逐步稳定
                性能持续优化
            b.稳定发展
                v1.0版本发布标志成熟
                保持向后兼容
                定期发布维护版本
        c.社区驱动
            a.开源协作
                接受社区Pull Request
                Issue讨论活跃
                定期发布新版本
            b.生态建设
                丰富的中间件生态
                完善的文档和示例
                活跃的技术社区
    c.设计理念
        a.性能优先
            a.零分配设计
                路由匹配零内存分配
                使用对象池复用对象
                减少GC压力
            b.高效算法
                Radix树路由算法
                快速的参数解析
                优化的中间件链
            c.基准测试
                在Go Web框架中性能领先
                QPS可达数十万级别
                低延迟响应
        b.简洁API
            a.链式调用
                router.GET().POST().PUT()
                流畅的API设计
                代码简洁易读
            b.直观命名
                方法名语义清晰
                符合Go语言习惯
                降低学习成本
        c.中间件机制
            a.洋葱模型
                请求从外到内穿过中间件
                响应从内到外返回
                灵活的执行流程控制
            b.可组合性
                中间件可自由组合
                支持全局和局部中间件
                易于扩展功能
    d.版本管理
        a.当前版本
            a.v1.x稳定版
                当前主流使用版本
                API稳定不变
                持续维护更新
            b.版本策略
                遵循语义化版本
                主版本号保持稳定
                小版本修复bug
        b.兼容性
            a.向后兼容
                v1.x系列保持API兼容
                升级无需修改代码
                平滑迁移
            b.废弃策略
                提前通知废弃API
                保留足够过渡期
                提供迁移指南
        c.更新节奏
            a.定期更新
                每月发布维护版本
                及时修复安全问题
                持续性能优化
            b.长期支持
                v1.x长期维护
                社区活跃响应
                稳定可靠

02.核心组件
    a.路由引擎
        a.httprouter基础
            a.Radix树实现
                使用Radix树(基数树)存储路由
                每个节点代表URL路径的一部分
                高效的路由查找算法,时间复杂度O(k)
            b.零内存分配
                路由匹配过程不产生内存分配
                使用预分配的内存池
                减少GC压力,提升性能
        b.高性能路由
            a.路由注册
                支持静态路由、参数路由、通配符路由
                路由在启动时编译成树结构
                运行时快速匹配
            b.路由匹配
                从根节点开始逐层匹配
                支持路径参数提取
                精确匹配优先于参数匹配
            c.性能优势
                比标准库http.ServeMux快数倍
                支持数万条路由高效匹配
                内存占用低
        c.参数解析
            a.路径参数
                /user/:id格式定义参数
                自动提取参数值
                支持多个参数
            b.查询参数
                自动解析URL查询字符串
                支持数组参数
                类型转换
        d.路由分组
            a.Group方法
                创建路由组,共享路径前缀
                支持嵌套分组
                便于模块化管理
            b.中间件共享
                组内路由共享中间件
                继承父组中间件
                灵活的中间件作用域
    b.中间件系统
        a.洋葱模型
            a.执行流程
                请求从最外层中间件开始
                逐层向内传递到处理函数
                响应从内向外逐层返回
            b.Next方法
                调用c.Next()执行下一个中间件
                可在Next前后添加逻辑
                实现请求前后处理
            c.Abort方法
                调用c.Abort()终止中间件链
                后续中间件不再执行
                用于认证失败等场景
        b.链式调用
            a.中间件注册
                Use()方法注册全局中间件
                按注册顺序执行
                支持注册多个中间件
            b.执行顺序
                全局中间件最先执行
                然后是分组中间件
                最后是路由中间件
        c.可组合性
            a.中间件组合
                多个中间件可自由组合
                实现复杂的业务逻辑
                代码复用性强
            b.条件中间件
                根据条件决定是否执行
                灵活控制中间件应用
        d.灵活扩展
            a.自定义中间件
                实现HandlerFunc接口
                访问Context对象
                可修改请求和响应
            b.第三方中间件
                丰富的社区中间件
                CORS、JWT、限流等
                即插即用
    c.上下文Context
        a.请求响应封装
            a.Request对象
                封装http.Request
                提供便捷的访问方法
                支持参数获取
            b.ResponseWriter
                封装http.ResponseWriter
                支持多种响应格式
                自动设置Content-Type
        b.数据传递
            a.Set/Get方法
                在中间件间传递数据
                类型安全的存储
                请求级别的数据共享
            b.Keys映射
                内部使用map存储
                支持任意类型值
                并发安全
        c.生命周期管理
            a.请求开始
                创建Context对象
                初始化内部状态
                绑定Request和Writer
            b.请求结束
                Context对象回收
                释放相关资源
                对象池复用
        d.类型安全
            a.类型断言
                Get返回interface{}
                需要类型断言
                提供类型安全的辅助方法
            b.辅助方法
                GetString、GetInt等
                自动类型转换
                提供默认值选项
    d.绑定验证
        a.数据绑定
            a.JSON绑定
                ShouldBindJSON自动解析JSON
                映射到结构体
                支持嵌套结构
            b.Form绑定
                ShouldBind解析表单数据
                支持multipart/form-data
                文件上传处理
            c.Query绑定
                ShouldBindQuery解析查询参数
                URL参数映射
                类型转换
        b.自动验证
            a.validator集成
                集成validator.v10库
                使用struct tag定义规则
                自动验证字段
            b.验证规则
                required、email、min、max等
                支持自定义验证器
                丰富的内置规则
        c.多格式支持
            a.支持格式
                JSON、XML、YAML、TOML
                Form、Query、URI
                自动识别Content-Type
            b.格式转换
                自动序列化和反序列化
                类型安全
                错误处理
        d.错误处理
            a.绑定错误
                返回详细的错误信息
                字段级别的错误
                便于调试
            b.验证错误
                ValidationErrors类型
                包含所有验证失败的字段
                可自定义错误消息

03.技术特点
    a.高性能
        a.零内存分配
            a.路由匹配优化
                Gin的路由匹配过程不产生内存分配
                使用Radix树算法,时间复杂度O(k),k为路径长度

                // 性能对比示例
                package main

                import (
                    "github.com/gin-gonic/gin"
                    "net/http"
                    "testing"
                )

                // Gin路由性能测试
                func BenchmarkGinRouting(b *testing.B) {
                    router := gin.New()
                    router.GET("/user/:id", func(c *gin.Context) {})

                    req, _ := http.NewRequest("GET", "/user/123", nil)
                    w := httptest.NewRecorder()

                    b.ReportAllocs()
                    b.ResetTimer()
                    for i := 0; i < b.N; i++ {
                        router.ServeHTTP(w, req)
                    }
                }
                // 结果:0 allocs/op(零内存分配)
            b.对象池复用
                Gin使用sync.Pool复用Context对象
                减少GC压力,提升性能

                // Context对象池实现原理
                var contextPool = sync.Pool{
                    New: func() interface{} {
                        return &Context{}
                    },
                }

                // 获取Context
                func (engine *Engine) allocateContext() *Context {
                    return contextPool.Get().(*Context)
                }

                // 回收Context
                func (engine *Engine) freeContext(c *Context) {
                    c.reset()
                    contextPool.Put(c)
                }
        b.快速路由
            a.Radix树算法
                Gin使用Radix树(压缩前缀树)存储路由
                每个节点代表URL路径的一部分
                查找效率远超map和slice

                // 路由树结构示例
                路由定义:
                /users
                /users/:id
                /users/:id/posts
                /products
                /products/:id

                Radix树结构:
                root
                ├── users
                │   ├── (handler)
                │   └── :id
                │       ├── (handler)
                │       └── /posts (handler)
                └── products
                    ├── (handler)
                    └── :id (handler)

                查找/users/123/posts:
                1. 从root开始
                2. 匹配"users" -> 进入users节点
                3. 匹配":id"参数 -> 提取123
                4. 匹配"/posts" -> 找到handler
                时间复杂度:O(路径长度)
            b.性能基准测试
                // 与其他框架对比
                BenchmarkGin-8              20000000    65.1 ns/op      0 B/op    0 allocs/op
                BenchmarkEcho-8             20000000    70.2 ns/op      0 B/op    0 allocs/op
                BenchmarkHttpRouter-8       20000000    62.3 ns/op      0 B/op    0 allocs/op
                BenchmarkStdMux-8            3000000   550.0 ns/op     32 B/op    1 allocs/op

                Gin在保持零分配的同时,性能接近纯httprouter
                比标准库http.ServeMux快8倍以上
        c.高效中间件
            a.中间件链优化
                Gin的中间件使用切片存储,按序执行
                通过索引控制执行流程,避免额外分配

                // 中间件执行原理
                type Context struct {
                    handlers HandlersChain  // []HandlerFunc
                    index    int8          // 当前执行位置
                }

                func (c *Context) Next() {
                    c.index++
                    for c.index < int8(len(c.handlers)) {
                        c.handlers[c.index](c)
                        c.index++
                    }
                }

                // 使用示例
                router := gin.New()
                router.Use(Logger(), Recovery())  // 全局中间件
                router.GET("/api", Auth(), Handler)  // 路由中间件

                执行顺序:Logger -> Recovery -> Auth -> Handler
    b.易用性
        a.简洁API
            a.链式调用
                Gin提供流畅的链式API,代码简洁易读

                // 基础示例
                router := gin.Default()

                // 链式定义路由
                router.GET("/users", getUsers).
                       POST("/users", createUser).
                       PUT("/users/:id", updateUser).
                       DELETE("/users/:id", deleteUser)

                // 路由分组链式调用
                v1 := router.Group("/api/v1")
                {
                    v1.GET("/users", getUsers)
                    v1.POST("/users", createUser)
                }

                v2 := router.Group("/api/v2").Use(AuthMiddleware())
                {
                    v2.GET("/users", getUsersV2)
                    v2.POST("/users", createUserV2)
                }
            b.直观的方法命名
                // 请求参数获取
                c.Param("id")              // 路径参数
                c.Query("name")            // 查询参数
                c.DefaultQuery("page", "1") // 带默认值的查询参数
                c.PostForm("username")     // 表单参数
                c.GetHeader("Authorization") // 请求头

                // 数据绑定
                c.ShouldBindJSON(&user)    // JSON绑定
                c.ShouldBind(&user)        // 自动识别格式
                c.ShouldBindQuery(&query)  // Query绑定

                // 响应
                c.JSON(200, data)          // JSON响应
                c.String(200, "ok")        // 字符串响应
                c.HTML(200, "index.html", data) // HTML响应
                c.Redirect(302, "/login")  // 重定向

                // 上下文数据
                c.Set("user", user)        // 设置数据
                user := c.MustGet("user")  // 获取数据
        b.完善的文档
            a.官方文档
                官方文档:https://gin-gonic.com/docs/
                中文文档:https://gin-gonic.com/zh-cn/docs/

                文档包含:
                - 快速开始指南
                - 完整的API参考
                - 实用示例代码
                - 最佳实践建议
                - 常见问题解答
            b.丰富示例
                // GitHub官方示例仓库
                https://github.com/gin-gonic/examples

                包含示例:
                - RESTful API完整实现
                - 文件上传下载
                - WebSocket聊天室
                - JWT认证
                - 优雅关闭
                - 自定义中间件
                - 测试用例
    c.可扩展性
        a.中间件机制
            a.全局中间件
                // 应用到所有路由
                router := gin.New()
                router.Use(gin.Logger())      // 日志中间件
                router.Use(gin.Recovery())    // 恢复中间件
                router.Use(Cors())            // CORS中间件
                router.Use(RateLimit())       // 限流中间件

                // 自定义全局中间件
                func CustomMiddleware() gin.HandlerFunc {
                    return func(c *gin.Context) {
                        // 请求前处理
                        start := time.Now()

                        c.Next()  // 执行后续处理器

                        // 请求后处理
                        latency := time.Since(start)
                        log.Printf("请求耗时: %v", latency)
                    }
                }

                router.Use(CustomMiddleware())
            b.路由级中间件
                // 应用到特定路由
                router.GET("/admin", AuthMiddleware(), AdminHandler)

                // 应用到路由组
                admin := router.Group("/admin")
                admin.Use(AuthMiddleware())
                {
                    admin.GET("/users", getUsers)
                    admin.POST("/users", createUser)
                }

                // 多个中间件组合
                router.GET("/api/data",
                    AuthMiddleware(),
                    RateLimitMiddleware(),
                    CacheMiddleware(),
                    DataHandler,
                )
        b.插件系统
            a.第三方中间件
                // CORS跨域
                import "github.com/gin-contrib/cors"
                router.Use(cors.Default())

                // JWT认证
                import "github.com/appleboy/gin-jwt/v2"
                authMiddleware, _ := jwt.New(&jwt.GinJWTMiddleware{...})
                router.Use(authMiddleware.MiddlewareFunc())

                // 限流
                import "github.com/ulule/limiter/v3"
                router.Use(limiter.Middleware())

                // Session
                import "github.com/gin-contrib/sessions"
                store := cookie.NewStore([]byte("secret"))
                router.Use(sessions.Sessions("mysession", store))

                // Gzip压缩
                import "github.com/gin-contrib/gzip"
                router.Use(gzip.Gzip(gzip.DefaultCompression))
    d.生态系统
        a.丰富的中间件库
            官方维护的中间件:
            - gin-contrib/cors          // CORS跨域
            - gin-contrib/sessions      // Session管理
            - gin-contrib/gzip          // Gzip压缩
            - gin-contrib/cache         // 缓存
            - gin-contrib/static        // 静态文件
            - gin-contrib/pprof         // 性能分析

            社区热门中间件:
            - gin-jwt                   // JWT认证
            - gin-swagger              // Swagger文档
            - gin-limiter              // 限流
            - gin-validator            // 数据验证
            - gin-i18n                 // 国际化
        b.活跃的社区
            GitHub Stars: 75k+
            Contributors: 400+
            Issues: 及时响应
            Pull Requests: 活跃合并

            社区资源:
            - Gitter聊天室
            - Stack Overflow标签
            - 中文社区论坛
            - 技术博客文章
            - 视频教程

1.2 核心特性

01.路由功能
    a.RESTful路由
        a.标准HTTP方法
            // GET - 获取资源
            router.GET("/users", func(c *gin.Context) {
                users := []User{
                    {ID: 1, Name: "Alice"},
                    {ID: 2, Name: "Bob"},
                }
                c.JSON(200, gin.H{
                    "code": 0,
                    "data": users,
                })
            })

            // POST - 创建资源
            router.POST("/users", func(c *gin.Context) {
                var user User
                if err := c.ShouldBindJSON(&user); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }
                // 保存到数据库...
                c.JSON(201, gin.H{
                    "code": 0,
                    "data": user,
                })
            })

            // PUT - 更新资源(完整更新)
            router.PUT("/users/:id", func(c *gin.Context) {
                id := c.Param("id")
                var user User
                if err := c.ShouldBindJSON(&user); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }
                // 更新数据库...
                c.JSON(200, gin.H{"code": 0, "message": "更新成功"})
            })

            // PATCH - 部分更新
            router.PATCH("/users/:id", func(c *gin.Context) {
                id := c.Param("id")
                var updates map[string]interface{}
                c.ShouldBindJSON(&updates)
                // 部分更新...
                c.JSON(200, gin.H{"code": 0})
            })

            // DELETE - 删除资源
            router.DELETE("/users/:id", func(c *gin.Context) {
                id := c.Param("id")
                // 删除数据库记录...
                c.JSON(204, nil)  // 204 No Content
            })
        b.语义化设计
            // 资源导向的URL设计
            GET    /users              // 获取用户列表
            GET    /users/:id          // 获取单个用户
            POST   /users              // 创建用户
            PUT    /users/:id          // 更新用户
            DELETE /users/:id          // 删除用户

            GET    /users/:id/posts    // 获取用户的文章
            POST   /users/:id/posts    // 为用户创建文章

            GET    /posts              // 获取文章列表
            GET    /posts/:id          // 获取文章详情
            GET    /posts/:id/comments // 获取文章评论

            // 完整示例
            func setupRoutes(router *gin.Engine) {
                // 用户相关
                users := router.Group("/users")
                {
                    users.GET("", listUsers)
                    users.GET("/:id", getUser)
                    users.POST("", createUser)
                    users.PUT("/:id", updateUser)
                    users.DELETE("/:id", deleteUser)

                    // 用户的文章
                    users.GET("/:id/posts", getUserPosts)
                    users.POST("/:id/posts", createUserPost)
                }

                // 文章相关
                posts := router.Group("/posts")
                {
                    posts.GET("", listPosts)
                    posts.GET("/:id", getPost)
                    posts.PUT("/:id", updatePost)
                    posts.DELETE("/:id", deletePost)

                    // 文章的评论
                    posts.GET("/:id/comments", getPostComments)
                    posts.POST("/:id/comments", createComment)
                }
            }
    b.路由参数
        a.路径参数
            // 单个参数
            router.GET("/user/:id", func(c *gin.Context) {
                id := c.Param("id")
                c.JSON(200, gin.H{"user_id": id})
            })

            // 多个参数
            router.GET("/posts/:year/:month/:day", func(c *gin.Context) {
                year := c.Param("year")
                month := c.Param("month")
                day := c.Param("day")

                c.JSON(200, gin.H{
                    "date": fmt.Sprintf("%s-%s-%s", year, month, day),
                })
            })

            // 参数验证和转换
            router.GET("/user/:id", func(c *gin.Context) {
                idStr := c.Param("id")
                id, err := strconv.Atoi(idStr)
                if err != nil {
                    c.JSON(400, gin.H{"error": "无效的用户ID"})
                    return
                }

                // 使用id查询数据库...
                user := getUserByID(id)
                c.JSON(200, user)
            })
        b.查询参数
            // 基础查询参数
            router.GET("/search", func(c *gin.Context) {
                keyword := c.Query("q")           // 获取q参数
                page := c.DefaultQuery("page", "1") // 默认值为1
                size := c.DefaultQuery("size", "10")

                c.JSON(200, gin.H{
                    "keyword": keyword,
                    "page": page,
                    "size": size,
                })
            })

            // 数组参数
            router.GET("/filter", func(c *gin.Context) {
                // URL: /filter?tags=go&tags=web&tags=api
                tags := c.QueryArray("tags")
                c.JSON(200, gin.H{"tags": tags})
            })

            // 复杂查询参数绑定
            type SearchQuery struct {
                Keyword  string   `form:"q" binding:"required"`
                Page     int      `form:"page" binding:"min=1"`
                Size     int      `form:"size" binding:"min=1,max=100"`
                Sort     string   `form:"sort"`
                Tags     []string `form:"tags"`
            }

            router.GET("/search", func(c *gin.Context) {
                var query SearchQuery
                if err := c.ShouldBindQuery(&query); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                // 执行搜索...
                results := search(query)
                c.JSON(200, results)
            })
        c.通配符路由
            // 匹配所有路径
            router.GET("/static/*filepath", func(c *gin.Context) {
                filepath := c.Param("filepath")
                // 提供静态文件服务
                c.File("./public" + filepath)
            })

            // 使用示例
            // /static/css/style.css  -> filepath = /css/style.css
            // /static/js/app.js      -> filepath = /js/app.js
            // /static/images/logo.png -> filepath = /images/logo.png

            // SPA应用的fallback路由
            router.NoRoute(func(c *gin.Context) {
                // 所有未匹配的路由返回index.html
                c.File("./dist/index.html")
            })

            // 完整的静态文件服务示例
            func main() {
                router := gin.Default()

                // 静态文件目录
                router.Static("/assets", "./assets")
                router.StaticFS("/public", http.Dir("./public"))
                router.StaticFile("/favicon.ico", "./favicon.ico")

                // API路由
                api := router.Group("/api")
                {
                    api.GET("/users", getUsers)
                }

                // SPA fallback
                router.NoRoute(func(c *gin.Context) {
                    c.File("./dist/index.html")
                })

                router.Run(":8080")
            }
    c.路由分组
        a.基础分组
            // 版本分组
            v1 := router.Group("/api/v1")
            {
                v1.GET("/users", getUsersV1)
                v1.POST("/users", createUserV1)
            }

            v2 := router.Group("/api/v2")
            {
                v2.GET("/users", getUsersV2)
                v2.POST("/users", createUserV2)
            }

            // 功能模块分组
            router := gin.Default()

            // 用户模块
            userGroup := router.Group("/users")
            {
                userGroup.GET("", listUsers)
                userGroup.GET("/:id", getUser)
                userGroup.POST("", createUser)
                userGroup.PUT("/:id", updateUser)
                userGroup.DELETE("/:id", deleteUser)
            }

            // 文章模块
            postGroup := router.Group("/posts")
            {
                postGroup.GET("", listPosts)
                postGroup.GET("/:id", getPost)
                postGroup.POST("", createPost)
            }

            // 评论模块
            commentGroup := router.Group("/comments")
            {
                commentGroup.GET("", listComments)
                commentGroup.POST("", createComment)
            }
        b.中间件共享
            // 公开API - 无需认证
            public := router.Group("/api/public")
            {
                public.GET("/posts", listPosts)
                public.GET("/posts/:id", getPost)
            }

            // 需要认证的API
            auth := router.Group("/api")
            auth.Use(AuthMiddleware())  // 应用认证中间件
            {
                auth.GET("/profile", getProfile)
                auth.PUT("/profile", updateProfile)

                // 用户相关
                users := auth.Group("/users")
                {
                    users.GET("", listUsers)
                    users.POST("", createUser)
                }
            }

            // 管理员API - 需要认证+权限
            admin := router.Group("/api/admin")
            admin.Use(AuthMiddleware())      // 认证
            admin.Use(AdminMiddleware())     // 管理员权限检查
            {
                admin.GET("/users", adminListUsers)
                admin.DELETE("/users/:id", adminDeleteUser)
                admin.GET("/stats", getStats)
            }

            // 完整示例
            func setupRouter() *gin.Engine {
                router := gin.Default()

                // 公开路由
                router.GET("/", indexHandler)
                router.GET("/about", aboutHandler)

                // API v1
                v1 := router.Group("/api/v1")
                v1.Use(RateLimitMiddleware())  // 限流
                {
                    // 公开接口
                    v1.GET("/posts", listPosts)

                    // 需要认证
                    authV1 := v1.Group("")
                    authV1.Use(AuthMiddleware())
                    {
                        authV1.POST("/posts", createPost)
                        authV1.PUT("/posts/:id", updatePost)
                    }
                }

                return router
            }
    d.路由优先级
        a.匹配规则
            // 优先级从高到低:
            // 1. 静态路由(精确匹配)
            // 2. 参数路由
            // 3. 通配符路由

            router.GET("/users/new", handler1)      // 优先级最高
            router.GET("/users/:id", handler2)      // 优先级中等
            router.GET("/users/*action", handler3)  // 优先级最低

            // 请求匹配示例:
            // GET /users/new     -> handler1(精确匹配)
            // GET /users/123     -> handler2(参数匹配)
            // GET /users/a/b/c   -> handler3(通配符匹配)

            // 路由冲突示例
            router.GET("/users/:id", handler1)
            router.GET("/users/:name", handler2)  // 错误!与上面冲突

            // 正确的做法:
            router.GET("/users/:id", func(c *gin.Context) {
                id := c.Param("id")
                // 根据id的格式判断是ID还是用户名
                if isNumeric(id) {
                    getUserByID(c, id)
                } else {
                    getUserByName(c, id)
                }
            })

02.中间件特性
    a.全局中间件
        a.应用级别中间件
            // 使用Default()创建路由器(包含Logger和Recovery)
            router := gin.Default()

            // 等价于:
            router := gin.New()
            router.Use(gin.Logger())
            router.Use(gin.Recovery())

            // 添加自定义全局中间件
            router.Use(Cors())           // CORS跨域
            router.Use(RateLimit())      // 限流
            router.Use(RequestID())      // 请求ID
            router.Use(Metrics())        // 指标收集

            // 完整示例
            func main() {
                router := gin.New()

                // 日志中间件
                router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
                    return fmt.Sprintf("[%s] %s %s %d %s\n",
                        param.TimeStamp.Format("2006-01-02 15:04:05"),
                        param.Method,
                        param.Path,
                        param.StatusCode,
                        param.Latency,
                    )
                }))

                // 恢复中间件
                router.Use(gin.Recovery())

                // CORS中间件
                router.Use(func(c *gin.Context) {
                    c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
                    c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")
                    c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")

                    if c.Request.Method == "OPTIONS" {
                        c.AbortWithStatus(204)
                        return
                    }

                    c.Next()
                })

                router.Run(":8080")
            }
        b.内置中间件详解
            // Logger中间件 - 记录请求日志
            router.Use(gin.Logger())
            // 输出格式:[GIN] 2024/01/01 - 12:00:00 | 200 |  1.234ms |  192.168.1.1 | GET  /api/users

            // 自定义Logger格式
            router.Use(gin.LoggerWithConfig(gin.LoggerConfig{
                Formatter: func(params gin.LogFormatterParams) string {
                    return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",
                        params.ClientIP,
                        params.TimeStamp.Format(time.RFC1123),
                        params.Method,
                        params.Path,
                        params.Request.Proto,
                        params.StatusCode,
                        params.Latency,
                        params.Request.UserAgent(),
                        params.ErrorMessage,
                    )
                },
                Output: os.Stdout,
                SkipPaths: []string{"/health"},  // 跳过健康检查路径
            }))

            // Recovery中间件 - panic恢复
            router.Use(gin.Recovery())

            // 自定义Recovery
            router.Use(gin.CustomRecovery(func(c *gin.Context, recovered interface{}) {
                if err, ok := recovered.(string); ok {
                    c.JSON(500, gin.H{
                        "error": "Internal Server Error",
                        "message": err,
                    })
                }
                c.AbortWithStatus(500)
            }))
    b.路由中间件
        a.特定路由中间件
            // 单个路由应用中间件
            router.GET("/admin", AuthMiddleware(), func(c *gin.Context) {
                c.JSON(200, gin.H{"message": "Admin page"})
            })

            // 多个中间件链
            router.GET("/api/data",
                AuthMiddleware(),       // 认证
                RateLimitMiddleware(),  // 限流
                CacheMiddleware(),      // 缓存
                func(c *gin.Context) {
                    c.JSON(200, gin.H{"data": "..."})
                },
            )

            // 中间件执行顺序示例
            func LogMiddleware(name string) gin.HandlerFunc {
                return func(c *gin.Context) {
                    fmt.Printf("[%s] Before\n", name)
                    c.Next()
                    fmt.Printf("[%s] After\n", name)
                }
            }

            router.GET("/test",
                LogMiddleware("M1"),
                LogMiddleware("M2"),
                func(c *gin.Context) {
                    fmt.Println("Handler")
                    c.JSON(200, gin.H{"ok": true})
                },
            )

            // 输出:
            // [M1] Before
            // [M2] Before
            // Handler
            // [M2] After
            // [M1] After
        b.分组中间件
            // 路由组应用中间件
            api := router.Group("/api")
            api.Use(LogMiddleware())  // 应用到整个组
            {
                api.GET("/users", getUsers)
                api.GET("/posts", getPosts)
            }

            // 嵌套分组中间件继承
            v1 := router.Group("/api/v1")
            v1.Use(RateLimitMiddleware())  // v1组的中间件
            {
                // 公开接口
                v1.GET("/posts", listPosts)

                // 需要认证的接口
                auth := v1.Group("/auth")
                auth.Use(AuthMiddleware())  // 继承v1的中间件,再加上认证
                {
                    auth.GET("/profile", getProfile)
                    auth.POST("/posts", createPost)
                }

                // 管理员接口
                admin := auth.Group("/admin")
                admin.Use(AdminMiddleware())  // 继承v1和auth的中间件,再加上管理员检查
                {
                    admin.DELETE("/users/:id", deleteUser)
                }
            }

            // 执行顺序:RateLimit -> Auth -> Admin -> Handler
    c.自定义中间件
        a.基础中间件实现
            // 简单的日志中间件
            func LoggerMiddleware() gin.HandlerFunc {
                return func(c *gin.Context) {
                    // 请求前
                    start := time.Now()
                    path := c.Request.URL.Path

                    // 处理请求
                    c.Next()

                    // 请求后
                    latency := time.Since(start)
                    status := c.Writer.Status()

                    log.Printf("[%s] %s %d %v",
                        c.Request.Method,
                        path,
                        status,
                        latency,
                    )
                }
            }

            // 使用
            router.Use(LoggerMiddleware())
        b.认证中间件
            // JWT认证中间件
            func AuthMiddleware() gin.HandlerFunc {
                return func(c *gin.Context) {
                    // 获取Token
                    token := c.GetHeader("Authorization")
                    if token == "" {
                        c.JSON(401, gin.H{"error": "未授权"})
                        c.Abort()
                        return
                    }

                    // 验证Token
                    claims, err := parseToken(token)
                    if err != nil {
                        c.JSON(401, gin.H{"error": "无效的Token"})
                        c.Abort()
                        return
                    }

                    // 将用户信息存储到上下文
                    c.Set("user_id", claims.UserID)
                    c.Set("username", claims.Username)

                    c.Next()
                }
            }

            // 使用示例
            router.GET("/profile", AuthMiddleware(), func(c *gin.Context) {
                userID := c.GetInt("user_id")
                username := c.GetString("username")

                c.JSON(200, gin.H{
                    "user_id": userID,
                    "username": username,
                })
            })
        c.限流中间件
            // 简单的限流中间件(基于IP)
            var limiter = make(map[string]*rate.Limiter)
            var mu sync.Mutex

            func RateLimitMiddleware(r rate.Limit, b int) gin.HandlerFunc {
                return func(c *gin.Context) {
                    ip := c.ClientIP()

                    mu.Lock()
                    if _, exists := limiter[ip]; !exists {
                        limiter[ip] = rate.NewLimiter(r, b)
                    }
                    mu.Unlock()

                    if !limiter[ip].Allow() {
                        c.JSON(429, gin.H{
                            "error": "请求过于频繁,请稍后再试",
                        })
                        c.Abort()
                        return
                    }

                    c.Next()
                }
            }

            // 使用:每秒最多10个请求,突发20个
            router.Use(RateLimitMiddleware(10, 20))
        d.CORS中间件
            // 完整的CORS中间件
            func CorsMiddleware() gin.HandlerFunc {
                return func(c *gin.Context) {
                    method := c.Request.Method
                    origin := c.Request.Header.Get("Origin")

                    if origin != "" {
                        // 允许的源
                        c.Header("Access-Control-Allow-Origin", origin)
                        // 允许的方法
                        c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
                        // 允许的头部
                        c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With")
                        // 允许携带凭证
                        c.Header("Access-Control-Allow-Credentials", "true")
                        // 预检请求缓存时间
                        c.Header("Access-Control-Max-Age", "86400")
                    }

                    // 处理OPTIONS预检请求
                    if method == "OPTIONS" {
                        c.AbortWithStatus(204)
                        return
                    }

                    c.Next()
                }
            }

            // 使用第三方CORS库(推荐)
            import "github.com/gin-contrib/cors"

            router.Use(cors.New(cors.Config{
                AllowOrigins:     []string{"https://example.com"},
                AllowMethods:     []string{"GET", "POST", "PUT", "DELETE"},
                AllowHeaders:     []string{"Origin", "Content-Type", "Authorization"},
                ExposeHeaders:    []string{"Content-Length"},
                AllowCredentials: true,
                MaxAge:           12 * time.Hour,
            }))

03.请求处理
    a.参数绑定
        a.JSON绑定
            // 定义结构体
            type User struct {
                Username string `json:"username" binding:"required,min=3,max=20"`
                Email    string `json:"email" binding:"required,email"`
                Age      int    `json:"age" binding:"required,gte=0,lte=120"`
                Password string `json:"password" binding:"required,min=6"`
            }

            // JSON绑定
            router.POST("/users", func(c *gin.Context) {
                var user User

                // ShouldBindJSON - 绑定失败不会自动返回400
                if err := c.ShouldBindJSON(&user); err != nil {
                    c.JSON(400, gin.H{
                        "error": "参数错误",
                        "details": err.Error(),
                    })
                    return
                }

                // 业务逻辑...
                c.JSON(201, gin.H{
                    "code": 0,
                    "data": user,
                })
            })

            // BindJSON - 绑定失败自动返回400
            router.POST("/users/v2", func(c *gin.Context) {
                var user User
                if err := c.BindJSON(&user); err != nil {
                    // 已经自动返回400,这里不会执行
                    return
                }
                c.JSON(201, user)
            })

            // 请求示例:
            // POST /users
            // Content-Type: application/json
            // {
            //   "username": "alice",
            //   "email": "[email protected]",
            //   "age": 25,
            //   "password": "secret123"
            // }
        b.Form绑定
            // 表单结构体
            type LoginForm struct {
                Username string `form:"username" binding:"required"`
                Password string `form:"password" binding:"required"`
                Remember bool   `form:"remember"`
            }

            // Form绑定(支持application/x-www-form-urlencoded和multipart/form-data)
            router.POST("/login", func(c *gin.Context) {
                var form LoginForm

                if err := c.ShouldBind(&form); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                // 验证用户名密码...
                c.JSON(200, gin.H{
                    "message": "登录成功",
                    "username": form.Username,
                })
            })

            // HTML表单示例:
            // <form method="POST" action="/login">
            //   <input name="username" value="alice">
            //   <input type="password" name="password" value="secret">
            //   <input type="checkbox" name="remember" value="true">
            //   <button type="submit">登录</button>
            // </form>

            // 或者使用curl:
            // curl -X POST http://localhost:8080/login \
            //   -d "username=alice&password=secret&remember=true"
        c.Query绑定
            // 查询参数结构体
            type SearchQuery struct {
                Keyword  string   `form:"q" binding:"required"`
                Page     int      `form:"page" binding:"min=1"`
                PageSize int      `form:"page_size" binding:"min=1,max=100"`
                Sort     string   `form:"sort" binding:"oneof=asc desc"`
                Tags     []string `form:"tags"`
            }

            // Query绑定
            router.GET("/search", func(c *gin.Context) {
                var query SearchQuery

                // 设置默认值
                query.Page = 1
                query.PageSize = 10
                query.Sort = "desc"

                if err := c.ShouldBindQuery(&query); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                // 执行搜索...
                results := performSearch(query)

                c.JSON(200, gin.H{
                    "query": query,
                    "results": results,
                })
            })

            // 请求示例:
            // GET /search?q=golang&page=2&page_size=20&sort=asc&tags=web&tags=api
        d.URI绑定
            // URI参数结构体
            type UserURI struct {
                ID   int    `uri:"id" binding:"required,min=1"`
                Name string `uri:"name" binding:"required"`
            }

            // URI绑定
            router.GET("/users/:id/:name", func(c *gin.Context) {
                var uri UserURI

                if err := c.ShouldBindUri(&uri); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                c.JSON(200, gin.H{
                    "id": uri.ID,
                    "name": uri.Name,
                })
            })

            // 请求示例:
            // GET /users/123/alice
    b.数据验证
        a.validator集成
            // Gin使用validator.v10进行数据验证
            import "github.com/go-playground/validator/v10"

            // 常用验证标签
            type Product struct {
                Name        string  `json:"name" binding:"required,min=2,max=100"`
                Price       float64 `json:"price" binding:"required,gt=0"`
                Stock       int     `json:"stock" binding:"required,gte=0"`
                Category    string  `json:"category" binding:"required,oneof=electronics books clothing"`
                Description string  `json:"description" binding:"max=500"`
                Email       string  `json:"email" binding:"omitempty,email"`
                URL         string  `json:"url" binding:"omitempty,url"`
                Tags        []string `json:"tags" binding:"required,min=1,max=5,dive,min=2,max=20"`
            }

            // 验证标签说明:
            // required     - 必填
            // omitempty    - 如果为空则跳过验证
            // min/max      - 最小/最大值(数字)或长度(字符串/数组)
            // gt/gte       - 大于/大于等于
            // lt/lte       - 小于/小于等于
            // eq/ne        - 等于/不等于
            // oneof        - 枚举值
            // email        - 邮箱格式
            // url          - URL格式
            // dive         - 深入数组/切片元素验证
        b.自定义验证
            // 注册自定义验证器
            import (
                "github.com/gin-gonic/gin/binding"
                "github.com/go-playground/validator/v10"
            )

            // 自定义验证函数
            func validateUsername(fl validator.FieldLevel) bool {
                username := fl.Field().String()
                // 用户名只能包含字母、数字和下划线
                matched, _ := regexp.MatchString(`^[a-zA-Z0-9_]+$`, username)
                return matched
            }

            // 注册验证器
            if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
                v.RegisterValidation("username", validateUsername)
            }

            // 使用自定义验证
            type RegisterForm struct {
                Username string `json:"username" binding:"required,username,min=3,max=20"`
                Password string `json:"password" binding:"required,min=6"`
            }

            router.POST("/register", func(c *gin.Context) {
                var form RegisterForm
                if err := c.ShouldBindJSON(&form); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }
                c.JSON(200, gin.H{"message": "注册成功"})
            })
        c.验证错误处理
            // 友好的错误消息
            func handleValidationError(err error) map[string]string {
                errors := make(map[string]string)

                if validationErrors, ok := err.(validator.ValidationErrors); ok {
                    for _, e := range validationErrors {
                        field := e.Field()
                        tag := e.Tag()

                        switch tag {
                        case "required":
                            errors[field] = field + "是必填项"
                        case "email":
                            errors[field] = field + "格式不正确"
                        case "min":
                            errors[field] = field + "长度不能小于" + e.Param()
                        case "max":
                            errors[field] = field + "长度不能大于" + e.Param()
                        default:
                            errors[field] = field + "验证失败"
                        }
                    }
                }

                return errors
            }

            // 使用
            router.POST("/users", func(c *gin.Context) {
                var user User
                if err := c.ShouldBindJSON(&user); err != nil {
                    c.JSON(400, gin.H{
                        "error": "参数验证失败",
                        "details": handleValidationError(err),
                    })
                    return
                }
                c.JSON(201, user)
            })
    c.文件上传
        a.单文件上传
            // 单文件上传
            router.POST("/upload", func(c *gin.Context) {
                // 获取文件
                file, err := c.FormFile("file")
                if err != nil {
                    c.JSON(400, gin.H{"error": "文件上传失败"})
                    return
                }

                // 验证文件大小(10MB)
                if file.Size > 10*1024*1024 {
                    c.JSON(400, gin.H{"error": "文件大小不能超过10MB"})
                    return
                }

                // 验证文件类型
                allowedTypes := map[string]bool{
                    "image/jpeg": true,
                    "image/png":  true,
                    "image/gif":  true,
                }

                contentType := file.Header.Get("Content-Type")
                if !allowedTypes[contentType] {
                    c.JSON(400, gin.H{"error": "只允许上传图片文件"})
                    return
                }

                // 生成唯一文件名
                ext := filepath.Ext(file.Filename)
                filename := fmt.Sprintf("%d%s", time.Now().Unix(), ext)
                filepath := filepath.Join("./uploads", filename)

                // 保存文件
                if err := c.SaveUploadedFile(file, filepath); err != nil {
                    c.JSON(500, gin.H{"error": "保存文件失败"})
                    return
                }

                c.JSON(200, gin.H{
                    "message": "上传成功",
                    "filename": filename,
                    "size": file.Size,
                })
            })

            // HTML表单:
            // <form method="POST" action="/upload" enctype="multipart/form-data">
            //   <input type="file" name="file">
            //   <button type="submit">上传</button>
            // </form>

            // curl示例:
            // curl -X POST http://localhost:8080/upload \
            //   -F "file=@/path/to/image.jpg"
        b.多文件上传
            // 多文件上传
            router.POST("/upload/multiple", func(c *gin.Context) {
                // 获取multipart form
                form, err := c.MultipartForm()
                if err != nil {
                    c.JSON(400, gin.H{"error": "获取表单失败"})
                    return
                }

                // 获取所有文件
                files := form.File["files"]

                // 限制文件数量
                if len(files) > 10 {
                    c.JSON(400, gin.H{"error": "最多只能上传10个文件"})
                    return
                }

                var uploadedFiles []string

                for _, file := range files {
                    // 验证每个文件
                    if file.Size > 10*1024*1024 {
                        continue
                    }

                    // 保存文件
                    filename := fmt.Sprintf("%d_%s", time.Now().UnixNano(), file.Filename)
                    filepath := filepath.Join("./uploads", filename)

                    if err := c.SaveUploadedFile(file, filepath); err != nil {
                        continue
                    }

                    uploadedFiles = append(uploadedFiles, filename)
                }

                c.JSON(200, gin.H{
                    "message": "上传完成",
                    "count": len(uploadedFiles),
                    "files": uploadedFiles,
                })
            })

            // HTML表单:
            // <form method="POST" action="/upload/multiple" enctype="multipart/form-data">
            //   <input type="file" name="files" multiple>
            //   <button type="submit">上传</button>
            // </form>
    d.请求上下文
        a.Context数据存储
            // 在中间件中设置数据
            func AuthMiddleware() gin.HandlerFunc {
                return func(c *gin.Context) {
                    // 验证token并获取用户信息
                    userID := 123
                    username := "alice"
                    role := "admin"

                    // 存储到Context
                    c.Set("user_id", userID)
                    c.Set("username", username)
                    c.Set("role", role)

                    c.Next()
                }
            }

            // 在处理器中获取数据
            router.GET("/profile", AuthMiddleware(), func(c *gin.Context) {
                // 方式1:Get返回interface{},需要类型断言
                userID, exists := c.Get("user_id")
                if !exists {
                    c.JSON(500, gin.H{"error": "用户信息不存在"})
                    return
                }

                // 方式2:使用类型安全的方法
                username := c.GetString("username")
                role := c.GetString("role")
                userIDInt := c.GetInt("user_id")

                // 方式3:MustGet(如果不存在会panic)
                // username := c.MustGet("username").(string)

                c.JSON(200, gin.H{
                    "user_id": userIDInt,
                    "username": username,
                    "role": role,
                })
            })

04.响应处理
    a.JSON响应
        a.基础JSON响应
            // 简单JSON响应
            router.GET("/api/hello", func(c *gin.Context) {
                c.JSON(200, gin.H{
                    "message": "Hello World",
                    "code": 0,
                })
            })

            // 结构体JSON响应
            type Response struct {
                Code    int         `json:"code"`
                Message string      `json:"message"`
                Data    interface{} `json:"data,omitempty"`
            }

            router.GET("/api/users", func(c *gin.Context) {
                users := []User{
                    {ID: 1, Name: "Alice"},
                    {ID: 2, Name: "Bob"},
                }

                c.JSON(200, Response{
                    Code:    0,
                    Message: "success",
                    Data:    users,
                })
            })

            // 统一响应格式封装
            func Success(c *gin.Context, data interface{}) {
                c.JSON(200, Response{
                    Code:    0,
                    Message: "success",
                    Data:    data,
                })
            }

            func Error(c *gin.Context, code int, message string) {
                c.JSON(code, Response{
                    Code:    -1,
                    Message: message,
                })
            }

            // 使用
            router.GET("/api/users", func(c *gin.Context) {
                users := getUsers()
                Success(c, users)
            })
        b.IndentedJSON
            // 格式化的JSON(带缩进,便于阅读)
            router.GET("/api/debug", func(c *gin.Context) {
                data := map[string]interface{}{
                    "user": map[string]interface{}{
                        "id":   1,
                        "name": "Alice",
                        "tags": []string{"admin", "developer"},
                    },
                }

                // 开发环境使用IndentedJSON
                c.IndentedJSON(200, data)

                // 输出:
                // {
                //   "user": {
                //     "id": 1,
                //     "name": "Alice",
                //     "tags": [
                //       "admin",
                //       "developer"
                //     ]
                //   }
                // }
            })
        c.SecureJSON和JSONP
            // SecureJSON - 防止JSON劫持
            router.GET("/api/secure", func(c *gin.Context) {
                data := []string{"apple", "banana"}
                // 在JSON前添加 "while(1);" 前缀
                c.SecureJSON(200, data)
                // 输出:while(1);["apple","banana"]
            })

            // JSONP - 支持跨域
            router.GET("/api/jsonp", func(c *gin.Context) {
                data := gin.H{
                    "message": "JSONP response",
                }
                // 使用callback参数
                c.JSONP(200, data)
            })

            // 请求:GET /api/jsonp?callback=handleResponse
            // 响应:handleResponse({"message":"JSONP response"})
    b.HTML渲染
        a.模板引擎配置
            // 加载模板
            router.LoadHTMLGlob("templates/*")

            // 或者加载嵌套目录
            router.LoadHTMLGlob("templates/**/*")

            // 渲染HTML
            router.GET("/", func(c *gin.Context) {
                c.HTML(200, "index.html", gin.H{
                    "title": "首页",
                    "user":  "Alice",
                })
            })

            // templates/index.html:
            // <!DOCTYPE html>
            // <html>
            // <head>
            //     <title>{{.title}}</title>
            // </head>
            // <body>
            //     <h1>Welcome, {{.user}}!</h1>
            // </body>
            // </html>
        b.自定义模板函数
            // 注册自定义函数
            router.SetFuncMap(template.FuncMap{
                "formatDate": func(t time.Time) string {
                    return t.Format("2006-01-02")
                },
                "upper": strings.ToUpper,
            })

            router.LoadHTMLGlob("templates/*")

            router.GET("/posts", func(c *gin.Context) {
                c.HTML(200, "posts.html", gin.H{
                    "posts": []Post{
                        {Title: "Hello", CreatedAt: time.Now()},
                    },
                })
            })

            // templates/posts.html:
            // {{range .posts}}
            //   <h2>{{upper .Title}}</h2>
            //   <p>{{formatDate .CreatedAt}}</p>
            // {{end}}
        c.静态文件服务
            // 静态文件目录
            router.Static("/assets", "./public/assets")
            router.StaticFS("/static", http.Dir("./static"))
            router.StaticFile("/favicon.ico", "./favicon.ico")

            // 使用示例:
            // /assets/css/style.css -> ./public/assets/css/style.css
            // /static/js/app.js     -> ./static/js/app.js
            // /favicon.ico          -> ./favicon.ico

            // 完整示例
            func main() {
                router := gin.Default()

                // 静态资源
                router.Static("/css", "./public/css")
                router.Static("/js", "./public/js")
                router.Static("/images", "./public/images")

                // HTML模板
                router.LoadHTMLGlob("templates/*")

                router.GET("/", func(c *gin.Context) {
                    c.HTML(200, "index.html", nil)
                })

                router.Run(":8080")
            }
    c.重定向
        a.HTTP重定向
            // 临时重定向(302)
            router.GET("/old-path", func(c *gin.Context) {
                c.Redirect(302, "/new-path")
            })

            // 永久重定向(301)
            router.GET("/old-page", func(c *gin.Context) {
                c.Redirect(301, "/new-page")
            })

            // 重定向到外部URL
            router.GET("/google", func(c *gin.Context) {
                c.Redirect(302, "https://www.google.com")
            })

            // 条件重定向
            router.GET("/dashboard", func(c *gin.Context) {
                if !isLoggedIn(c) {
                    c.Redirect(302, "/login")
                    return
                }
                c.HTML(200, "dashboard.html", nil)
            })
        b.路由重定向
            // 内部路由重定向
            router.GET("/test", func(c *gin.Context) {
                // 修改请求路径
                c.Request.URL.Path = "/test2"
                router.HandleContext(c)
            })

            router.GET("/test2", func(c *gin.Context) {
                c.JSON(200, gin.H{"message": "test2"})
            })

            // 带参数的重定向
            router.GET("/user/:id", func(c *gin.Context) {
                id := c.Param("id")
                c.Redirect(302, "/users/"+id+"/profile")
            })
    d.流式响应
        a.SSE(Server-Sent Events)
            // SSE实时推送
            router.GET("/events", func(c *gin.Context) {
                // 设置SSE响应头
                c.Writer.Header().Set("Content-Type", "text/event-stream")
                c.Writer.Header().Set("Cache-Control", "no-cache")
                c.Writer.Header().Set("Connection", "keep-alive")

                // 创建通道
                clientChan := make(chan string)

                // 发送事件
                go func() {
                    for i := 0; i < 10; i++ {
                        clientChan <- fmt.Sprintf("data: Message %d\n\n", i)
                        time.Sleep(time.Second)
                    }
                    close(clientChan)
                }()

                // 写入响应
                c.Stream(func(w io.Writer) bool {
                    if msg, ok := <-clientChan; ok {
                        c.SSEvent("message", msg)
                        return true
                    }
                    return false
                })
            })

            // 客户端JavaScript:
            // const eventSource = new EventSource('/events');
            // eventSource.onmessage = (event) => {
            //     console.log(event.data);
            // };
        b.分块传输
            // 流式传输大文件
            router.GET("/download/large", func(c *gin.Context) {
                file, err := os.Open("large-file.zip")
                if err != nil {
                    c.JSON(500, gin.H{"error": "文件打开失败"})
                    return
                }
                defer file.Close()

                // 设置响应头
                c.Writer.Header().Set("Content-Type", "application/octet-stream")
                c.Writer.Header().Set("Content-Disposition", "attachment; filename=large-file.zip")

                // 分块读取并写入
                buffer := make([]byte, 1024*1024) // 1MB buffer
                for {
                    n, err := file.Read(buffer)
                    if err != nil && err != io.EOF {
                        break
                    }
                    if n == 0 {
                        break
                    }

                    c.Writer.Write(buffer[:n])
                    c.Writer.Flush()
                }
            })
        c.实时日志流
            // 实时日志推送
            router.GET("/logs", func(c *gin.Context) {
                c.Writer.Header().Set("Content-Type", "text/plain")
                c.Writer.Header().Set("Transfer-Encoding", "chunked")

                // 模拟日志流
                for i := 0; i < 100; i++ {
                    log := fmt.Sprintf("[%s] Log message %d\n",
                        time.Now().Format("15:04:05"), i)

                    c.Writer.WriteString(log)
                    c.Writer.Flush()

                    time.Sleep(100 * time.Millisecond)
                }
            })

1.3 优缺点

01.主要优点
    a.性能卓越
        路由快速
        内存占用低
        并发性能好
        基准测试领先
    b.开发效率
        API简洁
        文档完善
        示例丰富
        快速上手
    c.生态丰富
        中间件多
        社区活跃
        第三方库
        工具完善
    d.可维护性
        代码清晰
        结构简单
        易于测试
        版本稳定

02.主要缺点
    a.功能相对简单
        非全栈框架
        需要组合使用
        缺少ORM
        无内置认证
    b.学习成本
        需要理解中间件
        路由规则
        上下文使用
        最佳实践
    c.错误处理
        需要手动处理
        无统一机制
        容易遗漏
        需要规范
    d.文档局限
        中文文档少
        高级特性说明不足
        最佳实践缺乏
        需要查阅源码

03.适用场景
    a.API服务
        RESTful API
        微服务
        后端服务
        高并发场景
    b.Web应用
        中小型应用
        快速原型
        内部工具
        管理后台
    c.性能要求高
        高并发
        低延迟
        资源受限
        云原生
    d.团队熟悉Go
        Go技术栈
        微服务架构
        容器化部署
        DevOps友好

04.不适用场景
    a.复杂业务
        需要全栈框架
        复杂权限
        工作流引擎
        企业级应用
    b.快速开发
        需要脚手架
        代码生成
        完整方案
        开箱即用
    c.传统Web
        服务端渲染为主
        复杂模板
        会话管理
        传统架构
    d.团队不熟悉Go
        学习成本
        开发效率
        维护困难
        技术债务

1.4 使用场景

01.微服务架构
    a.API网关
        a.路由转发
            a.请求路由和负载均衡
                // API网关路由转发
                type ServiceRegistry struct {
                    services map[string][]string // 服务名 -> 实例列表
                    mu       sync.RWMutex
                }

                func (sr *ServiceRegistry) GetInstance(service string) string {
                    sr.mu.RLock()
                    defer sr.mu.RUnlock()

                    instances := sr.services[service]
                    if len(instances) == 0 {
                        return ""
                    }

                    // 简单轮询负载均衡
                    idx := rand.Intn(len(instances))
                    return instances[idx]
                }

                // 网关路由
                router.Any("/api/users/*path", func(c *gin.Context) {
                    // 获取用户服务实例
                    instance := registry.GetInstance("user-service")
                    if instance == "" {
                        c.JSON(503, gin.H{"error": "服务不可用"})
                        return
                    }

                    // 转发请求
                    targetURL := instance + c.Request.URL.Path
                    proxyRequest(c, targetURL)
                })

                func proxyRequest(c *gin.Context, targetURL string) {
                    // 创建代理请求
                    req, _ := http.NewRequest(c.Request.Method, targetURL, c.Request.Body)

                    // 复制请求头
                    for key, values := range c.Request.Header {
                        for _, value := range values {
                            req.Header.Add(key, value)
                        }
                    }

                    // 发送请求
                    client := &http.Client{Timeout: 10 * time.Second}
                    resp, err := client.Do(req)
                    if err != nil {
                        c.JSON(502, gin.H{"error": "网关错误"})
                        return
                    }
                    defer resp.Body.Close()

                    // 返回响应
                    body, _ := ioutil.ReadAll(resp.Body)
                    c.Data(resp.StatusCode, resp.Header.Get("Content-Type"), body)
                }
        b.请求聚合
            a.多服务聚合
                // 聚合多个服务的数据
                router.GET("/api/dashboard", func(c *gin.Context) {
                    type DashboardData struct {
                        UserInfo  interface{} `json:"user_info"`
                        Orders    interface{} `json:"orders"`
                        Analytics interface{} `json:"analytics"`
                    }

                    var wg sync.WaitGroup
                    var data DashboardData

                    // 并行请求多个服务
                    wg.Add(3)

                    // 获取用户信息
                    go func() {
                        defer wg.Done()
                        resp, _ := http.Get("http://user-service/api/profile")
                        json.NewDecoder(resp.Body).Decode(&data.UserInfo)
                    }()

                    // 获取订单信息
                    go func() {
                        defer wg.Done()
                        resp, _ := http.Get("http://order-service/api/orders")
                        json.NewDecoder(resp.Body).Decode(&data.Orders)
                    }()

                    // 获取分析数据
                    go func() {
                        defer wg.Done()
                        resp, _ := http.Get("http://analytics-service/api/stats")
                        json.NewDecoder(resp.Body).Decode(&data.Analytics)
                    }()

                    wg.Wait()

                    c.JSON(200, data)
                })
    b.业务服务
        a.独立服务
            a.服务拆分
                按业务领域拆分服务
                单一职责原则
                独立部署和扩展
            b.服务边界
                明确的服务接口
                数据隔离
                松耦合设计
        b.轻量级特性
            a.快速启动
                Gin框架启动速度快
                资源占用少
                适合容器化部署
            b.高性能
                处理大量并发请求
                低延迟响应
                资源利用率高
    c.服务间通信
        a.HTTP API
            a.RESTful设计
                标准HTTP方法
                资源导向
                无状态通信
            b.JSON数据
                轻量级数据格式
                易于解析
                跨语言支持
        b.服务发现
            a.注册中心
                Consul、Etcd集成
                服务注册和发现
                健康检查
            b.客户端负载
                本地负载均衡
                故障转移
                性能优化
    d.容器化部署
        a.Docker支持
            a.镜像构建
                多阶段构建优化镜像大小
                静态编译减少依赖
                快速部署
            b.容器编排
                Kubernetes集成
                自动扩缩容
                滚动更新
        b.云原生特性
            a.12-Factor应用
                配置外部化
                无状态设计
                日志输出到stdout
            b.可观测性
                健康检查接口
                指标暴露
                分布式追踪

02.RESTful API
    a.移动端API
        a.iOS/Android应用
            a.移动端API设计
                // 移动端API示例
                router.Group("/api/v1/mobile").Use(AuthMiddleware()).
                {
                    // 用户相关
                    mobile.GET("/profile", func(c *gin.Context) {
                        userID := c.GetInt("user_id")
                        profile := getUserProfile(userID)

                        c.JSON(200, gin.H{
                            "code": 0,
                            "data": profile,
                            "version": "1.0.0", // API版本
                        })
                    })

                    // 列表接口(分页)
                    mobile.GET("/posts", func(c *gin.Context) {
                        page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
                        pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))

                        posts, total := getPostsWithPage(page, pageSize)

                        c.JSON(200, gin.H{
                            "code": 0,
                            "data": posts,
                            "page": gin.H{
                                "current": page,
                                "size": pageSize,
                                "total": total,
                            },
                        })
                    })
                }
    b.前后端分离
        a.SPA应用
            a.CORS配置
                import "github.com/gin-contrib/cors"

                // CORS中间件配置
                router.Use(cors.New(cors.Config{
                    AllowOrigins:     []string{"http://localhost:3000", "https://app.example.com"},
                    AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
                    AllowHeaders:     []string{"Origin", "Content-Type", "Authorization"},
                    ExposeHeaders:    []string{"Content-Length"},
                    AllowCredentials: true,
                    MaxAge:           12 * time.Hour,
                }))

                // API路由
                api := router.Group("/api")
                {
                    api.GET("/users", listUsers)
                    api.POST("/users", createUser)
                }

                // SPA路由(所有未匹配的路由返回index.html)
                router.NoRoute(func(c *gin.Context) {
                    if !strings.HasPrefix(c.Request.URL.Path, "/api/") {
                        c.File("./dist/index.html")
                    } else {
                        c.JSON(404, gin.H{"error": "接口不存在"})
                    }
                })
        b.跨域处理
            a.Token认证
                // JWT认证中间件
                func AuthMiddleware() gin.HandlerFunc {
                    return func(c *gin.Context) {
                        token := c.GetHeader("Authorization")

                        if token == "" {
                            c.JSON(401, gin.H{"error": "未授权"})
                            c.Abort()
                            return
                        }

                        // 验证Token
                        claims, err := validateJWT(token)
                        if err != nil {
                            c.JSON(401, gin.H{"error": "无效的token"})
                            c.Abort()
                            return
                        }

                        c.Set("user_id", claims.UserID)
                        c.Next()
                    }
                }

                // 使用
                router.POST("/api/login", func(c *gin.Context) {
                    var req LoginRequest
                    c.ShouldBindJSON(&req)

                    // 验证用户
                    user := authenticateUser(req.Username, req.Password)
                    if user == nil {
                        c.JSON(401, gin.H{"error": "用户名或密码错误"})
                        return
                    }

                    // 生成Token
                    token := generateJWT(user.ID)

                    c.JSON(200, gin.H{
                        "token": token,
                        "user": user,
                    })
                })
    c.第三方集成
        a.开放API
            a.API设计
                公开接口文档
                版本管理
                限流和配额
            b.认证授权
                API Key管理
                OAuth2授权
                权限控制
        b.Webhook
            a.事件通知
                异步事件推送
                重试机制
                签名验证
            b.集成场景
                支付回调
                消息通知
                数据同步
    d.内部服务
        a.后台管理
            a.管理界面
                数据CRUD操作
                权限管理
                配置管理
            b.业务功能
                用户管理
                内容管理
                统计分析
        b.数据服务
            a.查询接口
                复杂查询支持
                聚合统计
                导出功能
            b.批量操作
                批量导入
                批量更新
                异步处理

03.实时应用
    a.WebSocket
        a.实时通信
            // WebSocket升级和消息处理
            import "github.com/gorilla/websocket"

            var upgrader = websocket.Upgrader{
                CheckOrigin: func(r *http.Request) bool {
                    return true // 允许所有来源
                },
            }

            // WebSocket连接处理
            router.GET("/ws", func(c *gin.Context) {
                // 升级HTTP连接为WebSocket
                conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
                if err != nil {
                    log.Println("升级失败:", err)
                    return
                }
                defer conn.Close()

                // 读取消息
                for {
                    messageType, message, err := conn.ReadMessage()
                    if err != nil {
                        log.Println("读取失败:", err)
                        break
                    }

                    log.Printf("收到消息: %s", message)

                    // 回显消息
                    err = conn.WriteMessage(messageType, message)
                    if err != nil {
                        log.Println("写入失败:", err)
                        break
                    }
                }
            })

            // 客户端JavaScript:
            // const ws = new WebSocket('ws://localhost:8080/ws');
            // ws.onmessage = (event) => {
            //     console.log('收到:', event.data);
            // };
            // ws.send('Hello Server');
        b.在线聊天室
            // 聊天室实现
            type Client struct {
                conn *websocket.Conn
                send chan []byte
            }

            type Hub struct {
                clients    map[*Client]bool
                broadcast  chan []byte
                register   chan *Client
                unregister chan *Client
            }

            var hub = &Hub{
                clients:    make(map[*Client]bool),
                broadcast:  make(chan []byte),
                register:   make(chan *Client),
                unregister: make(chan *Client),
            }

            // Hub运行
            func (h *Hub) run() {
                for {
                    select {
                    case client := <-h.register:
                        h.clients[client] = true
                    case client := <-h.unregister:
                        if _, ok := h.clients[client]; ok {
                            delete(h.clients, client)
                            close(client.send)
                        }
                    case message := <-h.broadcast:
                        for client := range h.clients {
                            select {
                            case client.send <- message:
                            default:
                                close(client.send)
                                delete(h.clients, client)
                            }
                        }
                    }
                }
            }

            // WebSocket处理器
            router.GET("/chat", func(c *gin.Context) {
                conn, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
                client := &Client{conn: conn, send: make(chan []byte, 256)}
                hub.register <- client

                // 读取消息
                go func() {
                    defer func() {
                        hub.unregister <- client
                        conn.Close()
                    }()
                    for {
                        _, message, err := conn.ReadMessage()
                        if err != nil {
                            break
                        }
                        hub.broadcast <- message
                    }
                }()

                // 发送消息
                for message := range client.send {
                    conn.WriteMessage(websocket.TextMessage, message)
                }
            })

            // 启动Hub
            go hub.run()
    b.SSE(Server-Sent Events)
        a.服务器推送
            // SSE实时推送股票价格
            router.GET("/stock-prices", func(c *gin.Context) {
                c.Writer.Header().Set("Content-Type", "text/event-stream")
                c.Writer.Header().Set("Cache-Control", "no-cache")
                c.Writer.Header().Set("Connection", "keep-alive")

                ticker := time.NewTicker(time.Second)
                defer ticker.Stop()

                for {
                    select {
                    case <-ticker.C:
                        // 生成随机股票价格
                        price := 100 + rand.Float64()*10
                        data := fmt.Sprintf("data: {\"symbol\":\"AAPL\",\"price\":%.2f}\n\n", price)

                        c.Writer.WriteString(data)
                        c.Writer.Flush()

                    case <-c.Request.Context().Done():
                        return
                    }
                }
            })

            // 客户端JavaScript:
            // const eventSource = new EventSource('/stock-prices');
            // eventSource.onmessage = (event) => {
            //     const data = JSON.parse(event.data);
            //     console.log(`${data.symbol}: $${data.price}`);
            // };
        b.实时通知
            // 实时通知系统
            type Notification struct {
                ID      int       `json:"id"`
                Type    string    `json:"type"`
                Message string    `json:"message"`
                Time    time.Time `json:"time"`
            }

            router.GET("/notifications", func(c *gin.Context) {
                c.Writer.Header().Set("Content-Type", "text/event-stream")
                c.Writer.Header().Set("Cache-Control", "no-cache")

                // 模拟通知流
                notifications := []Notification{
                    {1, "info", "新消息", time.Now()},
                    {2, "warning", "系统更新", time.Now()},
                    {3, "success", "操作成功", time.Now()},
                }

                for _, notif := range notifications {
                    data, _ := json.Marshal(notif)
                    fmt.Fprintf(c.Writer, "event: notification\n")
                    fmt.Fprintf(c.Writer, "data: %s\n\n", data)
                    c.Writer.Flush()
                    time.Sleep(2 * time.Second)
                }
            })
    c.长轮询
        a.消息推送
            // 长轮询实现
            var messageQueue = make(chan string, 100)

            // 发送消息接口
            router.POST("/send-message", func(c *gin.Context) {
                var msg struct {
                    Content string `json:"content"`
                }
                c.ShouldBindJSON(&msg)

                messageQueue <- msg.Content
                c.JSON(200, gin.H{"status": "sent"})
            })

            // 长轮询接收消息
            router.GET("/poll-messages", func(c *gin.Context) {
                timeout := time.After(30 * time.Second)

                select {
                case msg := <-messageQueue:
                    c.JSON(200, gin.H{
                        "message": msg,
                        "timestamp": time.Now(),
                    })
                case <-timeout:
                    c.JSON(200, gin.H{
                        "message": nil,
                        "timeout": true,
                    })
                }
            })

            // 客户端示例:
            // async function pollMessages() {
            //     while (true) {
            //         const response = await fetch('/poll-messages');
            //         const data = await response.json();
            //         if (data.message) {
            //             console.log('新消息:', data.message);
            //         }
            //     }
            // }
    d.流式处理
        a.大文件传输
            // 流式上传大文件
            router.POST("/upload/stream", func(c *gin.Context) {
                file, header, err := c.Request.FormFile("file")
                if err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }
                defer file.Close()

                // 创建目标文件
                dst, err := os.Create("./uploads/" + header.Filename)
                if err != nil {
                    c.JSON(500, gin.H{"error": "创建文件失败"})
                    return
                }
                defer dst.Close()

                // 流式复制
                written, err := io.Copy(dst, file)
                if err != nil {
                    c.JSON(500, gin.H{"error": "保存失败"})
                    return
                }

                c.JSON(200, gin.H{
                    "filename": header.Filename,
                    "size": written,
                })
            })

            // 流式下载大文件
            router.GET("/download/stream/:filename", func(c *gin.Context) {
                filename := c.Param("filename")
                filepath := "./files/" + filename

                file, err := os.Open(filepath)
                if err != nil {
                    c.JSON(404, gin.H{"error": "文件不存在"})
                    return
                }
                defer file.Close()

                // 获取文件信息
                stat, _ := file.Stat()

                // 设置响应头
                c.Writer.Header().Set("Content-Disposition", "attachment; filename="+filename)
                c.Writer.Header().Set("Content-Type", "application/octet-stream")
                c.Writer.Header().Set("Content-Length", fmt.Sprintf("%d", stat.Size()))

                // 流式传输
                io.Copy(c.Writer, file)
            })

04.工具服务
    a.代理服务
        a.反向代理
            // 简单的反向代理
            router.Any("/proxy/*path", func(c *gin.Context) {
                targetURL := "http://backend-server.com" + c.Param("path")

                // 创建代理请求
                proxyReq, _ := http.NewRequest(c.Request.Method, targetURL, c.Request.Body)

                // 复制请求头
                for key, values := range c.Request.Header {
                    for _, value := range values {
                        proxyReq.Header.Add(key, value)
                    }
                }

                // 发送请求
                client := &http.Client{Timeout: 30 * time.Second}
                resp, err := client.Do(proxyReq)
                if err != nil {
                    c.JSON(502, gin.H{"error": "代理请求失败"})
                    return
                }
                defer resp.Body.Close()

                // 复制响应头
                for key, values := range resp.Header {
                    for _, value := range values {
                        c.Writer.Header().Add(key, value)
                    }
                }

                // 返回响应
                c.Status(resp.StatusCode)
                io.Copy(c.Writer, resp.Body)
            })
        b.负载均衡
            // 简单的轮询负载均衡
            var backends = []string{
                "http://server1:8080",
                "http://server2:8080",
                "http://server3:8080",
            }
            var currentBackend = 0
            var mu sync.Mutex

            router.Any("/api/*path", func(c *gin.Context) {
                mu.Lock()
                backend := backends[currentBackend]
                currentBackend = (currentBackend + 1) % len(backends)
                mu.Unlock()

                // 转发请求到后端
                targetURL := backend + c.Request.URL.Path
                // ... 代理逻辑
            })
    b.文件服务
        a.图片处理
            // 图片缩略图生成
            import "github.com/disintegration/imaging"

            router.GET("/thumbnail/:filename", func(c *gin.Context) {
                filename := c.Param("filename")
                width := c.DefaultQuery("w", "200")
                height := c.DefaultQuery("h", "200")

                // 打开原图
                src, err := imaging.Open("./images/" + filename)
                if err != nil {
                    c.JSON(404, gin.H{"error": "图片不存在"})
                    return
                }

                // 生成缩略图
                w, _ := strconv.Atoi(width)
                h, _ := strconv.Atoi(height)
                thumb := imaging.Thumbnail(src, w, h, imaging.Lanczos)

                // 输出图片
                c.Writer.Header().Set("Content-Type", "image/jpeg")
                imaging.Encode(c.Writer, thumb, imaging.JPEG)
            })

            // 请求: GET /thumbnail/photo.jpg?w=300&h=300
    c.监控服务
        a.健康检查
            // 健康检查端点
            router.GET("/health", func(c *gin.Context) {
                // 检查数据库连接
                dbOK := checkDatabase()
                // 检查Redis连接
                redisOK := checkRedis()

                status := "healthy"
                code := 200

                if !dbOK || !redisOK {
                    status = "unhealthy"
                    code = 503
                }

                c.JSON(code, gin.H{
                    "status": status,
                    "checks": gin.H{
                        "database": dbOK,
                        "redis": redisOK,
                    },
                    "timestamp": time.Now(),
                })
            })

            // Kubernetes liveness/readiness probe
            router.GET("/healthz", func(c *gin.Context) {
                c.String(200, "OK")
            })
        b.指标收集
            // Prometheus指标
            import "github.com/prometheus/client_golang/prometheus/promhttp"

            router.GET("/metrics", gin.WrapH(promhttp.Handler()))

            // 自定义指标
            var (
                requestCounter = prometheus.NewCounterVec(
                    prometheus.CounterOpts{
                        Name: "http_requests_total",
                        Help: "Total number of HTTP requests",
                    },
                    []string{"method", "path", "status"},
                )
            )

            func MetricsMiddleware() gin.HandlerFunc {
                return func(c *gin.Context) {
                    c.Next()

                    requestCounter.WithLabelValues(
                        c.Request.Method,
                        c.Request.URL.Path,
                        strconv.Itoa(c.Writer.Status()),
                    ).Inc()
                }
            }

            router.Use(MetricsMiddleware())

1.5 快速开始

01.安装配置
    a.环境要求
        a.Go版本
            // 检查Go版本
            $ go version
            go version go1.21.0 darwin/amd64

            // 要求:Go 1.16+
            // 推荐:Go 1.20+

            // 安装Go(macOS)
            $ brew install go

            // 安装Go(Linux)
            $ wget https://go.dev/dl/go1.21.0.linux-amd64.tar.gz
            $ sudo tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz
            $ export PATH=$PATH:/usr/local/go/bin
        b.开发工具
            推荐IDE:
            - VS Code + Go扩展
            - GoLand(JetBrains)
            - Vim/Neovim + vim-go

            必备工具:
            - go mod(包管理)
            - gofmt(代码格式化)
            - golint(代码检查)
            - delve(调试器)

            // 安装开发工具
            $ go install golang.org/x/tools/gopls@latest
            $ go install github.com/go-delve/delve/cmd/dlv@latest
    b.安装Gin
        a.使用go get
            // 安装Gin框架
            $ go get -u github.com/gin-gonic/gin

            // 或者使用go mod
            $ go mod init myapp
            $ go get github.com/gin-gonic/gin

            // go.mod文件内容:
            module myapp

            go 1.21

            require github.com/gin-gonic/gin v1.9.1
        b.验证安装
            // 创建测试文件 main.go
            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()
            }

            // 运行
            $ go run main.go

            // 测试
            $ curl http://localhost:8080/ping
            {"message":"pong"}
    c.项目初始化
        a.创建项目结构
            // 标准项目结构
            myapp/
            ├── cmd/
            │   └── server/
            │       └── main.go          # 主程序入口
            ├── internal/
            │   ├── handler/             # HTTP处理器
            │   ├── service/             # 业务逻辑
            │   ├── repository/          # 数据访问
            │   └── model/               # 数据模型
            ├── pkg/                     # 公共库
            ├── configs/                 # 配置文件
            ├── scripts/                 # 脚本
            ├── docs/                    # 文档
            ├── go.mod
            ├── go.sum
            └── README.md

            // 创建项目
            $ mkdir -p myapp/{cmd/server,internal/{handler,service,repository,model},pkg,configs}
            $ cd myapp
            $ go mod init github.com/username/myapp
        b.编写主程序
            // cmd/server/main.go
            package main

            import (
                "log"
                "github.com/gin-gonic/gin"
            )

            func main() {
                // 设置运行模式
                gin.SetMode(gin.ReleaseMode)

                // 创建路由
                router := setupRouter()

                // 启动服务
                if err := router.Run(":8080"); err != nil {
                    log.Fatal("启动失败:", err)
                }
            }

            func setupRouter() *gin.Engine {
                router := gin.Default()

                // 健康检查
                router.GET("/health", func(c *gin.Context) {
                    c.JSON(200, gin.H{"status": "ok"})
                })

                // API路由
                api := router.Group("/api/v1")
                {
                    api.GET("/users", getUsers)
                    api.POST("/users", createUser)
                }

                return router
            }

            func getUsers(c *gin.Context) {
                c.JSON(200, gin.H{"users": []string{"alice", "bob"}})
            }

            func createUser(c *gin.Context) {
                c.JSON(201, gin.H{"message": "created"})
            }
    d.配置文件
        a.配置管理
            // configs/config.yaml
            server:
              port: 8080
              mode: release

            database:
              host: localhost
              port: 5432
              name: myapp
              user: postgres
              password: secret

            redis:
              host: localhost
              port: 6379
              db: 0

            // 使用Viper读取配置
            import "github.com/spf13/viper"

            func loadConfig() {
                viper.SetConfigName("config")
                viper.SetConfigType("yaml")
                viper.AddConfigPath("./configs")

                if err := viper.ReadInConfig(); err != nil {
                    log.Fatal("读取配置失败:", err)
                }
            }

            // 使用配置
            port := viper.GetString("server.port")
            dbHost := viper.GetString("database.host")
    b.安装Gin
        go get命令
        go.mod管理
        版本选择
        依赖下载
    c.项目初始化
        目录结构
        go.mod创建
        main.go编写
        配置文件
    d.开发工具
        IDE配置
        调试工具
        热重载
        代码提示

02.Hello World
    a.基础示例
        a.完整代码
            // main.go
            package main

            import (
                "github.com/gin-gonic/gin"
                "net/http"
            )

            func main() {
                // 创建默认引擎(包含Logger和Recovery中间件)
                router := gin.Default()

                // 定义路由
                router.GET("/", func(c *gin.Context) {
                    c.JSON(http.StatusOK, gin.H{
                        "message": "Hello World!",
                        "status": "success",
                    })
                })

                router.GET("/ping", func(c *gin.Context) {
                    c.JSON(200, gin.H{"message": "pong"})
                })

                // 启动服务,默认监听0.0.0.0:8080
                router.Run()
            }

            // 运行:
            // $ go run main.go
            // [GIN-debug] Listening and serving HTTP on :8080
        b.自定义端口
            // 指定端口启动
            router.Run(":3000")  // 监听3000端口
            router.Run("0.0.0.0:8080")  // 指定IP和端口

            // 使用http.Server
            srv := &http.Server{
                Addr:    ":8080",
                Handler: router,
            }
            srv.ListenAndServe()

            // HTTPS启动
            router.RunTLS(":443", "cert.pem", "key.pem")
    b.路由处理
        a.处理函数详解
            // 基础处理函数
            func helloHandler(c *gin.Context) {
                // 获取查询参数
                name := c.DefaultQuery("name", "Guest")

                // 设置响应
                c.JSON(200, gin.H{
                    "message": "Hello, " + name,
                    "timestamp": time.Now(),
                })
            }

            router.GET("/hello", helloHandler)

            // 请求:GET /hello?name=Alice
            // 响应:{"message": "Hello, Alice", "timestamp": "2024-01-15T10:30:00Z"}
        b.Context常用方法
            router.GET("/demo", func(c *gin.Context) {
                // 获取参数
                id := c.Param("id")              // 路径参数
                name := c.Query("name")          // 查询参数
                page := c.DefaultQuery("page", "1")  // 带默认值

                // 获取请求头
                userAgent := c.GetHeader("User-Agent")

                // 获取客户端IP
                ip := c.ClientIP()

                // 设置响应头
                c.Header("X-Custom-Header", "value")

                // 返回JSON
                c.JSON(200, gin.H{
                    "id": id,
                    "name": name,
                    "page": page,
                    "user_agent": userAgent,
                    "ip": ip,
                })
            })
    c.运行测试
        a.多种测试方式
            // 1. 浏览器访问
            // 打开浏览器访问:http://localhost:8080/

            // 2. curl测试
            $ curl http://localhost:8080/
            {"message":"Hello World!","status":"success"}

            $ curl http://localhost:8080/ping
            {"message":"pong"}

            $ curl "http://localhost:8080/hello?name=Alice"
            {"message":"Hello, Alice"}

            // 3. curl POST请求
            $ curl -X POST http://localhost:8080/users \
              -H "Content-Type: application/json" \
              -d '{"name":"Alice","email":"[email protected]"}'

            // 4. Postman测试
            // - 创建新请求
            // - 选择GET方法
            // - 输入URL: http://localhost:8080/
            // - 点击Send

            // 5. HTTPie测试(更友好的curl)
            $ http GET localhost:8080/
            $ http POST localhost:8080/users name=Alice [email protected]
    d.代码说明
        a.核心API解释
            // gin.Default() vs gin.New()

            // Default包含Logger和Recovery中间件
            router := gin.Default()
            // 等价于:
            router := gin.New()
            router.Use(gin.Logger())
            router.Use(gin.Recovery())

            // router.GET() - 注册GET路由
            // 参数1:路径
            // 参数2:处理函数(可以多个,形成中间件链)
            router.GET("/path", middleware1, middleware2, handler)

            // c.JSON() - 返回JSON响应
            // 参数1:HTTP状态码
            // 参数2:要序列化的数据
            c.JSON(200, gin.H{"key": "value"})

            // Run() - 启动HTTP服务
            // 默认监听 :8080
            router.Run()
            // 自定义端口
            router.Run(":3000")

03.基础路由
    a.GET请求
        a.查询列表
            // 获取用户列表
            router.GET("/api/users", func(c *gin.Context) {
                // 获取分页参数
                page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
                pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))

                // 查询数据库
                users, total := getUserList(page, pageSize)

                c.JSON(200, gin.H{
                    "code": 0,
                    "data": users,
                    "pagination": gin.H{
                        "page":       page,
                        "page_size":  pageSize,
                        "total":      total,
                        "total_page": (total + pageSize - 1) / pageSize,
                    },
                })
            })

            // 请求:GET /api/users?page=1&page_size=20
        b.查询详情
            // 获取用户详情
            router.GET("/api/users/:id", func(c *gin.Context) {
                id := c.Param("id")
                userID, err := strconv.Atoi(id)
                if err != nil {
                    c.JSON(400, gin.H{"error": "无效的用户ID"})
                    return
                }

                user, err := getUserByID(userID)
                if err != nil {
                    c.JSON(404, gin.H{"error": "用户不存在"})
                    return
                }

                c.JSON(200, gin.H{
                    "code": 0,
                    "data": user,
                })
            })
    b.POST请求
        a.创建资源
            // 创建用户
            type CreateUserRequest struct {
                Username string `json:"username" binding:"required,min=3,max=20"`
                Email    string `json:"email" binding:"required,email"`
                Password string `json:"password" binding:"required,min=6"`
            }

            router.POST("/api/users", func(c *gin.Context) {
                var req CreateUserRequest

                // 解析请求体
                if err := c.ShouldBindJSON(&req); err != nil {
                    c.JSON(400, gin.H{
                        "error": "参数验证失败",
                        "details": err.Error(),
                    })
                    return
                }

                // 检查用户名是否存在
                if userExists(req.Username) {
                    c.JSON(400, gin.H{"error": "用户名已存在"})
                    return
                }

                // 创建用户
                user, err := createUser(req)
                if err != nil {
                    c.JSON(500, gin.H{"error": "创建失败"})
                    return
                }

                c.JSON(201, gin.H{
                    "code": 0,
                    "message": "创建成功",
                    "data": user,
                })
            })
    c.PUT请求
        a.更新资源
            // 更新用户信息
            type UpdateUserRequest struct {
                Username string `json:"username" binding:"omitempty,min=3,max=20"`
                Email    string `json:"email" binding:"omitempty,email"`
                Age      int    `json:"age" binding:"omitempty,gte=0,lte=120"`
            }

            router.PUT("/api/users/:id", func(c *gin.Context) {
                id := c.Param("id")
                userID, _ := strconv.Atoi(id)

                var req UpdateUserRequest
                if err := c.ShouldBindJSON(&req); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                // 检查用户是否存在
                user, err := getUserByID(userID)
                if err != nil {
                    c.JSON(404, gin.H{"error": "用户不存在"})
                    return
                }

                // 更新用户
                if err := updateUser(userID, req); err != nil {
                    c.JSON(500, gin.H{"error": "更新失败"})
                    return
                }

                c.JSON(200, gin.H{
                    "code": 0,
                    "message": "更新成功",
                })
            })
    d.DELETE请求
        a.删除资源
            // 删除用户
            router.DELETE("/api/users/:id", func(c *gin.Context) {
                id := c.Param("id")
                userID, _ := strconv.Atoi(id)

                // 权限检查
                currentUserID := c.GetInt("user_id")
                if !canDeleteUser(currentUserID, userID) {
                    c.JSON(403, gin.H{"error": "无权删除此用户"})
                    return
                }

                // 检查用户是否存在
                if !userExists(userID) {
                    c.JSON(404, gin.H{"error": "用户不存在"})
                    return
                }

                // 删除用户
                if err := deleteUser(userID); err != nil {
                    c.JSON(500, gin.H{"error": "删除失败"})
                    return
                }

                c.JSON(200, gin.H{
                    "code": 0,
                    "message": "删除成功",
                })
            })

04.项目结构
    a.标准结构
        a.完整目录布局
            myapp/
            ├── cmd/
            │   └── server/
            │       └── main.go              # 程序入口
            ├── internal/                    # 私有代码
            │   ├── handler/                 # HTTP处理器
            │   │   ├── user_handler.go
            │   │   └── post_handler.go
            │   ├── service/                 # 业务逻辑
            │   │   ├── user_service.go
            │   │   └── post_service.go
            │   ├── repository/              # 数据访问
            │   │   ├── user_repository.go
            │   │   └── post_repository.go
            │   ├── model/                   # 数据模型
            │   │   ├── user.go
            │   │   └── post.go
            │   └── middleware/              # 中间件
            │       ├── auth.go
            │       └── logger.go
            ├── pkg/                         # 公共库
            │   ├── utils/
            │   ├── errors/
            │   └── response/
            ├── configs/                     # 配置文件
            │   ├── config.yaml
            │   ├── config.dev.yaml
            │   └── config.prod.yaml
            ├── scripts/                     # 脚本
            │   ├── build.sh
            │   └── deploy.sh
            ├── migrations/                  # 数据库迁移
            │   └── 001_init.sql
            ├── docs/                        # 文档
            │   └── api.md
            ├── go.mod
            ├── go.sum
            ├── Makefile
            ├── Dockerfile
            └── README.md
    b.分层架构
        a.Handler层
            // internal/handler/user_handler.go
            package handler

            import (
                "myapp/internal/service"
                "github.com/gin-gonic/gin"
            )

            type UserHandler struct {
                userService service.UserService
            }

            func NewUserHandler(userService service.UserService) *UserHandler {
                return &UserHandler{
                    userService: userService,
                }
            }

            // 获取用户列表
            func (h *UserHandler) List(c *gin.Context) {
                page := c.DefaultQuery("page", "1")
                pageSize := c.DefaultQuery("page_size", "10")

                users, total, err := h.userService.GetList(page, pageSize)
                if err != nil {
                    c.JSON(500, gin.H{"error": err.Error()})
                    return
                }

                c.JSON(200, gin.H{
                    "code": 0,
                    "data": users,
                    "total": total,
                })
            }

            // 创建用户
            func (h *UserHandler) Create(c *gin.Context) {
                var req CreateUserRequest
                if err := c.ShouldBindJSON(&req); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                user, err := h.userService.Create(req)
                if err != nil {
                    c.JSON(500, gin.H{"error": err.Error()})
                    return
                }

                c.JSON(201, gin.H{"code": 0, "data": user})
            }
        b.Service层
            // internal/service/user_service.go
            package service

            import (
                "myapp/internal/model"
                "myapp/internal/repository"
            )

            type UserService interface {
                GetList(page, pageSize string) ([]model.User, int64, error)
                GetByID(id int) (*model.User, error)
                Create(req CreateUserRequest) (*model.User, error)
                Update(id int, req UpdateUserRequest) error
                Delete(id int) error
            }

            type userService struct {
                userRepo repository.UserRepository
            }

            func NewUserService(userRepo repository.UserRepository) UserService {
                return &userService{
                    userRepo: userRepo,
                }
            }

            func (s *userService) Create(req CreateUserRequest) (*model.User, error) {
                // 业务逻辑验证
                if exists, _ := s.userRepo.ExistsByUsername(req.Username); exists {
                    return nil, errors.New("用户名已存在")
                }

                // 密码加密
                hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
                if err != nil {
                    return nil, err
                }

                user := &model.User{
                    Username: req.Username,
                    Email:    req.Email,
                    Password: string(hashedPassword),
                }

                // 保存到数据库
                if err := s.userRepo.Create(user); err != nil {
                    return nil, err
                }

                return user, nil
            }
        c.Repository层
            // internal/repository/user_repository.go
            package repository

            import (
                "myapp/internal/model"
                "gorm.io/gorm"
            )

            type UserRepository interface {
                Create(user *model.User) error
                FindByID(id int) (*model.User, error)
                FindAll(offset, limit int) ([]model.User, int64, error)
                Update(user *model.User) error
                Delete(id int) error
                ExistsByUsername(username string) (bool, error)
            }

            type userRepository struct {
                db *gorm.DB
            }

            func NewUserRepository(db *gorm.DB) UserRepository {
                return &userRepository{db: db}
            }

            func (r *userRepository) Create(user *model.User) error {
                return r.db.Create(user).Error
            }

            func (r *userRepository) FindByID(id int) (*model.User, error) {
                var user model.User
                err := r.db.First(&user, id).Error
                return &user, err
            }

            func (r *userRepository) FindAll(offset, limit int) ([]model.User, int64, error) {
                var users []model.User
                var total int64

                r.db.Model(&model.User{}).Count(&total)
                err := r.db.Offset(offset).Limit(limit).Find(&users).Error

                return users, total, err
            }
        d.Model层
            // internal/model/user.go
            package model

            import (
                "time"
                "gorm.io/gorm"
            )

            type User struct {
                ID        uint           `gorm:"primaryKey" json:"id"`
                Username  string         `gorm:"uniqueIndex;size:50" json:"username"`
                Email     string         `gorm:"uniqueIndex;size:100" json:"email"`
                Password  string         `gorm:"size:255" json:"-"`  // 不返回给前端
                Age       int            `json:"age"`
                Status    int            `gorm:"default:1" json:"status"`
                CreatedAt time.Time      `json:"created_at"`
                UpdatedAt time.Time      `json:"updated_at"`
                DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
            }

            // DTO - 数据传输对象
            type CreateUserRequest struct {
                Username string `json:"username" binding:"required,min=3,max=20"`
                Email    string `json:"email" binding:"required,email"`
                Password string `json:"password" binding:"required,min=6"`
            }

            type UpdateUserRequest struct {
                Username string `json:"username" binding:"omitempty,min=3,max=20"`
                Email    string `json:"email" binding:"omitempty,email"`
                Age      int    `json:"age" binding:"omitempty,gte=0,lte=120"`
            }

            // VO - 视图对象
            type UserVO struct {
                ID       uint   `json:"id"`
                Username string `json:"username"`
                Email    string `json:"email"`
                Age      int    `json:"age"`
            }
    c.配置管理
        a.配置文件
            // configs/config.yaml
            server:
              host: 0.0.0.0
              port: 8080
              mode: release  # debug, release, test
              read_timeout: 60s
              write_timeout: 60s

            database:
              driver: mysql
              host: localhost
              port: 3306
              database: myapp
              username: root
              password: secret
              charset: utf8mb4
              max_idle_conns: 10
              max_open_conns: 100
              conn_max_lifetime: 3600s

            redis:
              host: localhost
              port: 6379
              password: ""
              db: 0
              pool_size: 10

            log:
              level: info
              format: json
              output: stdout
              file: logs/app.log

            jwt:
              secret: your-secret-key
              expire: 24h
        b.配置加载
            // internal/config/config.go
            package config

            import (
                "github.com/spf13/viper"
                "log"
            )

            type Config struct {
                Server   ServerConfig   `mapstructure:"server"`
                Database DatabaseConfig `mapstructure:"database"`
                Redis    RedisConfig    `mapstructure:"redis"`
                Log      LogConfig      `mapstructure:"log"`
                JWT      JWTConfig      `mapstructure:"jwt"`
            }

            type ServerConfig struct {
                Host         string `mapstructure:"host"`
                Port         int    `mapstructure:"port"`
                Mode         string `mapstructure:"mode"`
                ReadTimeout  string `mapstructure:"read_timeout"`
                WriteTimeout string `mapstructure:"write_timeout"`
            }

            type DatabaseConfig struct {
                Driver          string `mapstructure:"driver"`
                Host            string `mapstructure:"host"`
                Port            int    `mapstructure:"port"`
                Database        string `mapstructure:"database"`
                Username        string `mapstructure:"username"`
                Password        string `mapstructure:"password"`
                MaxIdleConns    int    `mapstructure:"max_idle_conns"`
                MaxOpenConns    int    `mapstructure:"max_open_conns"`
                ConnMaxLifetime string `mapstructure:"conn_max_lifetime"`
            }

            func Load() (*Config, error) {
                viper.SetConfigName("config")
                viper.SetConfigType("yaml")
                viper.AddConfigPath("./configs")

                // 环境变量覆盖
                viper.AutomaticEnv()

                if err := viper.ReadInConfig(); err != nil {
                    return nil, err
                }

                var config Config
                if err := viper.Unmarshal(&config); err != nil {
                    return nil, err
                }

                return &config, nil
            }
    d.依赖注入
        a.Wire依赖注入
            // internal/wire/wire.go
            //go:build wireinject
            // +build wireinject

            package wire

            import (
                "github.com/google/wire"
                "myapp/internal/handler"
                "myapp/internal/service"
                "myapp/internal/repository"
            )

            func InitializeApp() (*App, error) {
                wire.Build(
                    // 数据库
                    NewDB,
                    // Repository
                    repository.NewUserRepository,
                    repository.NewPostRepository,
                    // Service
                    service.NewUserService,
                    service.NewPostService,
                    // Handler
                    handler.NewUserHandler,
                    handler.NewPostHandler,
                    // App
                    NewApp,
                )
                return &App{}, nil
            }

            // internal/wire/app.go
            package wire

            import (
                "myapp/internal/handler"
                "github.com/gin-gonic/gin"
            )

            type App struct {
                Router      *gin.Engine
                UserHandler *handler.UserHandler
                PostHandler *handler.PostHandler
            }

            func NewApp(
                userHandler *handler.UserHandler,
                postHandler *handler.PostHandler,
            ) *App {
                router := gin.Default()

                // 注册路由
                api := router.Group("/api/v1")
                {
                    users := api.Group("/users")
                    {
                        users.GET("", userHandler.List)
                        users.POST("", userHandler.Create)
                        users.GET("/:id", userHandler.Get)
                        users.PUT("/:id", userHandler.Update)
                        users.DELETE("/:id", userHandler.Delete)
                    }
                }

                return &App{
                    Router:      router,
                    UserHandler: userHandler,
                    PostHandler: postHandler,
                }
            }

            // 生成代码:
            // $ wire gen ./internal/wire

05.开发规范
    a.代码组织
        a.包划分规范
            // 按功能模块划分包
            internal/
            ├── user/           # 用户模块
            │   ├── handler.go
            │   ├── service.go
            │   └── repository.go
            ├── post/           # 文章模块
            │   ├── handler.go
            │   ├── service.go
            │   └── repository.go
            └── auth/           # 认证模块
                ├── handler.go
                ├── service.go
                └── middleware.go

            // 或按层次划分
            internal/
            ├── handler/        # 所有处理器
            ├── service/        # 所有服务
            ├── repository/     # 所有仓储
            └── model/          # 所有模型

            // 命名规范:
            // - 包名使用小写单词
            // - 避免下划线和驼峰
            // - 包名应简洁有意义
            // - 避免使用common、util等通用名称
        b.文件命名
            // 文件命名规范:
            user_handler.go      # 推荐:下划线分隔
            user_service.go
            user_repository.go

            // 测试文件:
            user_handler_test.go
            user_service_test.go

            // 避免:
            UserHandler.go       # 不推荐:驼峰命名
            user-handler.go      # 不推荐:连字符
        c.函数命名
            // 导出函数:首字母大写
            func NewUserService() UserService {}
            func GetUserByID(id int) (*User, error) {}

            // 私有函数:首字母小写
            func validateUser(user *User) error {}
            func hashPassword(password string) string {}

            // 接口方法:动词开头
            type UserService interface {
                Create(user *User) error
                Update(user *User) error
                Delete(id int) error
                FindByID(id int) (*User, error)
                FindAll() ([]User, error)
            }

            // 布尔函数:is/has/can开头
            func isValidEmail(email string) bool {}
            func hasPermission(userID int, resource string) bool {}
            func canDelete(userID int) bool {}
        d.注释规范
            // Package user 提供用户相关的业务逻辑处理
            package user

            // UserService 定义用户服务接口
            // 包含用户的CRUD操作和业务逻辑
            type UserService interface {
                // Create 创建新用户
                // 参数:
                //   user: 用户信息
                // 返回:
                //   error: 创建失败时返回错误
                Create(user *User) error

                // GetByID 根据ID获取用户
                // 参数:
                //   id: 用户ID
                // 返回:
                //   *User: 用户信息
                //   error: 用户不存在或查询失败时返回错误
                GetByID(id int) (*User, error)
            }

            // TODO: 实现用户导出功能
            // FIXME: 修复并发更新问题
            // NOTE: 此处需要优化性能
            // HACK: 临时解决方案,待重构
    b.错误处理
        a.错误定义
            // pkg/errors/errors.go
            package errors

            import "errors"

            var (
                // 业务错误
                ErrUserNotFound      = errors.New("用户不存在")
                ErrUserExists        = errors.New("用户已存在")
                ErrInvalidPassword   = errors.New("密码错误")
                ErrUnauthorized      = errors.New("未授权")
                ErrForbidden         = errors.New("无权限")

                // 系统错误
                ErrDatabase          = errors.New("数据库错误")
                ErrInternal          = errors.New("内部错误")
            )

            // 自定义错误类型
            type AppError struct {
                Code    int    `json:"code"`
                Message string `json:"message"`
                Err     error  `json:"-"`
            }

            func (e *AppError) Error() string {
                if e.Err != nil {
                    return e.Err.Error()
                }
                return e.Message
            }

            func NewAppError(code int, message string) *AppError {
                return &AppError{
                    Code:    code,
                    Message: message,
                }
            }
        b.错误处理
            // Service层错误处理
            func (s *userService) Create(req CreateUserRequest) (*User, error) {
                // 参数验证
                if req.Username == "" {
                    return nil, errors.New("用户名不能为空")
                }

                // 业务逻辑
                exists, err := s.userRepo.ExistsByUsername(req.Username)
                if err != nil {
                    return nil, fmt.Errorf("检查用户名失败: %w", err)
                }
                if exists {
                    return nil, ErrUserExists
                }

                // 数据库操作
                user := &User{Username: req.Username}
                if err := s.userRepo.Create(user); err != nil {
                    return nil, fmt.Errorf("创建用户失败: %w", err)
                }

                return user, nil
            }

            // Handler层错误处理
            func (h *UserHandler) Create(c *gin.Context) {
                var req CreateUserRequest
                if err := c.ShouldBindJSON(&req); err != nil {
                    c.JSON(400, gin.H{"error": "参数错误", "details": err.Error()})
                    return
                }

                user, err := h.userService.Create(req)
                if err != nil {
                    // 根据错误类型返回不同状态码
                    switch {
                    case errors.Is(err, ErrUserExists):
                        c.JSON(400, gin.H{"error": err.Error()})
                    case errors.Is(err, ErrDatabase):
                        c.JSON(500, gin.H{"error": "系统错误"})
                    default:
                        c.JSON(500, gin.H{"error": err.Error()})
                    }
                    return
                }

                c.JSON(201, gin.H{"code": 0, "data": user})
            }
    c.日志规范
        a.日志级别
            import "go.uber.org/zap"

            // 初始化日志
            logger, _ := zap.NewProduction()
            defer logger.Sync()

            // Debug: 调试信息
            logger.Debug("调试信息",
                zap.String("user_id", "123"),
                zap.Int("count", 10),
            )

            // Info: 一般信息
            logger.Info("用户登录",
                zap.String("username", "alice"),
                zap.String("ip", "192.168.1.1"),
            )

            // Warn: 警告信息
            logger.Warn("请求过于频繁",
                zap.String("ip", "192.168.1.1"),
                zap.Int("count", 100),
            )

            // Error: 错误信息
            logger.Error("数据库连接失败",
                zap.Error(err),
                zap.String("host", "localhost"),
            )

            // Fatal: 致命错误(会退出程序)
            logger.Fatal("启动失败", zap.Error(err))
        b.日志格式
            // 结构化日志
            logger.Info("用户操作",
                zap.String("action", "create"),
                zap.String("user_id", "123"),
                zap.String("resource", "post"),
                zap.Int("resource_id", 456),
                zap.Duration("latency", time.Since(start)),
            )

            // 输出:
            // {
            //   "level": "info",
            //   "ts": 1642345678.123,
            //   "msg": "用户操作",
            //   "action": "create",
            //   "user_id": "123",
            //   "resource": "post",
            //   "resource_id": 456,
            //   "latency": 0.123
            // }

            // 请求日志中间件
            func LoggerMiddleware(logger *zap.Logger) gin.HandlerFunc {
                return func(c *gin.Context) {
                    start := time.Now()
                    path := c.Request.URL.Path

                    c.Next()

                    latency := time.Since(start)
                    logger.Info("请求处理",
                        zap.String("method", c.Request.Method),
                        zap.String("path", path),
                        zap.Int("status", c.Writer.Status()),
                        zap.Duration("latency", latency),
                        zap.String("ip", c.ClientIP()),
                    )
                }
            }
    d.测试规范
        a.单元测试
            // user_service_test.go
            package service

            import (
                "testing"
                "github.com/stretchr/testify/assert"
                "github.com/stretchr/testify/mock"
            )

            // Mock Repository
            type MockUserRepository struct {
                mock.Mock
            }

            func (m *MockUserRepository) Create(user *User) error {
                args := m.Called(user)
                return args.Error(0)
            }

            func (m *MockUserRepository) ExistsByUsername(username string) (bool, error) {
                args := m.Called(username)
                return args.Bool(0), args.Error(1)
            }

            // 测试用例
            func TestUserService_Create(t *testing.T) {
                // 准备
                mockRepo := new(MockUserRepository)
                service := NewUserService(mockRepo)

                req := CreateUserRequest{
                    Username: "alice",
                    Email:    "[email protected]",
                }

                // Mock返回值
                mockRepo.On("ExistsByUsername", "alice").Return(false, nil)
                mockRepo.On("Create", mock.Anything).Return(nil)

                // 执行
                user, err := service.Create(req)

                // 断言
                assert.NoError(t, err)
                assert.NotNil(t, user)
                assert.Equal(t, "alice", user.Username)

                // 验证Mock调用
                mockRepo.AssertExpectations(t)
            }

            func TestUserService_Create_UserExists(t *testing.T) {
                mockRepo := new(MockUserRepository)
                service := NewUserService(mockRepo)

                req := CreateUserRequest{Username: "alice"}

                mockRepo.On("ExistsByUsername", "alice").Return(true, nil)

                user, err := service.Create(req)

                assert.Error(t, err)
                assert.Nil(t, user)
                assert.Equal(t, ErrUserExists, err)
            }

            // 运行测试:
            // $ go test ./internal/service -v
            // $ go test ./internal/service -cover
        b.集成测试
            // user_handler_test.go
            package handler

            import (
                "bytes"
                "encoding/json"
                "net/http"
                "net/http/httptest"
                "testing"
                "github.com/gin-gonic/gin"
                "github.com/stretchr/testify/assert"
            )

            func TestUserHandler_Create(t *testing.T) {
                // 设置测试模式
                gin.SetMode(gin.TestMode)

                // 创建测试路由
                router := gin.Default()
                handler := NewUserHandler(mockUserService)
                router.POST("/users", handler.Create)

                // 准备测试数据
                reqBody := map[string]interface{}{
                    "username": "alice",
                    "email":    "[email protected]",
                    "password": "password123",
                }
                jsonData, _ := json.Marshal(reqBody)

                // 创建测试请求
                req, _ := http.NewRequest("POST", "/users", bytes.NewBuffer(jsonData))
                req.Header.Set("Content-Type", "application/json")

                // 执行请求
                w := httptest.NewRecorder()
                router.ServeHTTP(w, req)

                // 断言响应
                assert.Equal(t, 201, w.Code)

                var response map[string]interface{}
                json.Unmarshal(w.Body.Bytes(), &response)
                assert.Equal(t, float64(0), response["code"])
            }

            // 运行测试:
            // $ go test ./internal/handler -v

1.6 项目结构

01.目录组织
    a.标准布局
        a.完整项目结构
            myapp/
            ├── cmd/                        # 主程序入口
            │   └── server/
            │       └── main.go
            ├── internal/                   # 私有代码(不可被外部导入)
            │   ├── handler/
            │   ├── service/
            │   ├── repository/
            │   ├── model/
            │   └── middleware/
            ├── pkg/                        # 公共库(可被外部导入)
            │   ├── utils/
            │   ├── logger/
            │   └── response/
            ├── api/                        # API定义
            │   ├── proto/                  # Protobuf定义
            │   └── swagger/                # Swagger文档
            ├── configs/                    # 配置文件
            │   ├── config.yaml
            │   ├── config.dev.yaml
            │   └── config.prod.yaml
            ├── scripts/                    # 脚本
            │   ├── build.sh
            │   ├── deploy.sh
            │   └── migrate.sh
            ├── docs/                       # 文档
            │   ├── api.md
            │   └── architecture.md
            ├── test/                       # 测试
            │   ├── integration/
            │   └── e2e/
            ├── web/                        # 前端资源
            │   ├── static/
            │   └── templates/
            ├── migrations/                 # 数据库迁移
            │   ├── 001_init.sql
            │   └── 002_add_users.sql
            ├── build/                      # 构建脚本
            │   └── package/
            ├── deployments/                # 部署配置
            │   ├── docker/
            │   │   └── Dockerfile
            │   └── kubernetes/
            │       ├── deployment.yaml
            │       └── service.yaml
            ├── go.mod
            ├── go.sum
            ├── Makefile
            └── README.md
        b.cmd目录详解
            // cmd/server/main.go - 程序入口
            package main

            import (
                "context"
                "log"
                "net/http"
                "os"
                "os/signal"
                "syscall"
                "time"

                "myapp/internal/config"
                "myapp/internal/wire"
                "github.com/gin-gonic/gin"
            )

            func main() {
                // 加载配置
                cfg, err := config.Load()
                if err != nil {
                    log.Fatal("加载配置失败:", err)
                }

                // 设置Gin模式
                gin.SetMode(cfg.Server.Mode)

                // 初始化应用(使用Wire依赖注入)
                app, cleanup, err := wire.InitializeApp(cfg)
                if err != nil {
                    log.Fatal("初始化应用失败:", err)
                }
                defer cleanup()

                // 创建HTTP服务器
                srv := &http.Server{
                    Addr:         ":" + cfg.Server.Port,
                    Handler:      app.Router,
                    ReadTimeout:  time.Duration(cfg.Server.ReadTimeout) * time.Second,
                    WriteTimeout: time.Duration(cfg.Server.WriteTimeout) * time.Second,
                }

                // 启动服务器
                go func() {
                    log.Printf("服务器启动在 %s", srv.Addr)
                    if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
                        log.Fatal("服务器启动失败:", err)
                    }
                }()

                // 优雅关闭
                quit := make(chan os.Signal, 1)
                signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
                <-quit

                log.Println("正在关闭服务器...")

                ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
                defer cancel()

                if err := srv.Shutdown(ctx); err != nil {
                    log.Fatal("服务器强制关闭:", err)
                }

                log.Println("服务器已退出")
            }
    b.配置目录
        a.多环境配置
            // configs/config.yaml - 默认配置
            server:
              host: 0.0.0.0
              port: 8080
              mode: release
              read_timeout: 60
              write_timeout: 60

            database:
              driver: mysql
              host: localhost
              port: 3306
              database: myapp
              username: root
              password: secret
              max_idle_conns: 10
              max_open_conns: 100

            // configs/config.dev.yaml - 开发环境
            server:
              mode: debug
              port: 3000

            database:
              host: localhost
              database: myapp_dev

            log:
              level: debug

            // configs/config.prod.yaml - 生产环境
            server:
              mode: release
              port: 80

            database:
              host: db.production.com
              database: myapp_prod
              max_open_conns: 200

            log:
              level: info
              output: file
              file: /var/log/myapp/app.log
        b.脚本示例
            # scripts/build.sh - 构建脚本
            #!/bin/bash

            APP_NAME="myapp"
            VERSION=$(git describe --tags --always)
            BUILD_TIME=$(date +%Y%m%d%H%M%S)

            echo "Building ${APP_NAME} ${VERSION}..."

            # 清理
            rm -rf build/
            mkdir -p build/

            # 构建
            go build -ldflags "\
                -X main.Version=${VERSION} \
                -X main.BuildTime=${BUILD_TIME}" \
                -o build/${APP_NAME} \
                ./cmd/server

            echo "Build complete: build/${APP_NAME}"

            # scripts/deploy.sh - 部署脚本
            #!/bin/bash

            ENV=${1:-dev}

            echo "Deploying to ${ENV}..."

            # 构建
            ./scripts/build.sh

            # 上传到服务器
            scp build/myapp user@server:/opt/myapp/
            scp configs/config.${ENV}.yaml user@server:/opt/myapp/config.yaml

            # 重启服务
            ssh user@server "systemctl restart myapp"

            echo "Deployment complete"

            # scripts/migrate.sh - 数据库迁移
            #!/bin/bash

            DB_HOST=${DB_HOST:-localhost}
            DB_NAME=${DB_NAME:-myapp}
            DB_USER=${DB_USER:-root}

            echo "Running migrations..."

            for file in migrations/*.sql; do
                echo "Executing $file..."
                mysql -h${DB_HOST} -u${DB_USER} -p ${DB_NAME} < $file
            done

            echo "Migrations complete"
    c.资源目录
        a.静态文件组织
            web/
            ├── static/
            │   ├── css/
            │   │   ├── main.css
            │   │   └── admin.css
            │   ├── js/
            │   │   ├── app.js
            │   │   └── vendor/
            │   ├── images/
            │   │   ├── logo.png
            │   │   └── icons/
            │   └── fonts/
            └── templates/
                ├── layouts/
                │   ├── base.html
                │   └── admin.html
                ├── pages/
                │   ├── index.html
                │   └── about.html
                └── partials/
                    ├── header.html
                    └── footer.html

            // 在Gin中使用
            router.Static("/static", "./web/static")
            router.LoadHTMLGlob("web/templates/**/*")

            router.GET("/", func(c *gin.Context) {
                c.HTML(200, "pages/index.html", gin.H{
                    "title": "首页",
                })
            })
        b.数据库迁移
            // migrations/001_init.sql
            CREATE TABLE IF NOT EXISTS users (
                id INT AUTO_INCREMENT PRIMARY KEY,
                username VARCHAR(50) UNIQUE NOT NULL,
                email VARCHAR(100) UNIQUE NOT NULL,
                password VARCHAR(255) NOT NULL,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                deleted_at TIMESTAMP NULL,
                INDEX idx_username (username),
                INDEX idx_email (email)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

            // migrations/002_add_posts.sql
            CREATE TABLE IF NOT EXISTS posts (
                id INT AUTO_INCREMENT PRIMARY KEY,
                user_id INT NOT NULL,
                title VARCHAR(200) NOT NULL,
                content TEXT,
                status TINYINT DEFAULT 0,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
                INDEX idx_user_id (user_id),
                INDEX idx_status (status)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

            // 使用golang-migrate工具
            // $ migrate -path migrations -database "mysql://root:secret@tcp(localhost:3306)/myapp" up
    d.构建目录
        a.Dockerfile
            # deployments/docker/Dockerfile
            # 多阶段构建
            FROM golang:1.21-alpine AS builder

            WORKDIR /app

            # 复制依赖文件
            COPY go.mod go.sum ./
            RUN go mod download

            # 复制源代码
            COPY . .

            # 构建
            RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main ./cmd/server

            # 运行阶段
            FROM alpine:latest

            RUN apk --no-cache add ca-certificates

            WORKDIR /root/

            # 从构建阶段复制二进制文件
            COPY --from=builder /app/main .
            COPY --from=builder /app/configs ./configs

            EXPOSE 8080

            CMD ["./main"]

            # 构建镜像:
            # $ docker build -t myapp:latest -f deployments/docker/Dockerfile .

            # 运行容器:
            # $ docker run -p 8080:8080 -e APP_ENV=production myapp:latest
        b.Kubernetes部署
            # deployments/kubernetes/deployment.yaml
            apiVersion: apps/v1
            kind: Deployment
            metadata:
              name: myapp
              labels:
                app: myapp
            spec:
              replicas: 3
              selector:
                matchLabels:
                  app: myapp
              template:
                metadata:
                  labels:
                    app: myapp
                spec:
                  containers:
                  - name: myapp
                    image: myapp:latest
                    ports:
                    - containerPort: 8080
                    env:
                    - name: APP_ENV
                      value: "production"
                    - name: DB_HOST
                      valueFrom:
                        configMapKeyRef:
                          name: myapp-config
                          key: db.host
                    resources:
                      limits:
                        cpu: "1"
                        memory: "512Mi"
                      requests:
                        cpu: "500m"
                        memory: "256Mi"
                    livenessProbe:
                      httpGet:
                        path: /health
                        port: 8080
                      initialDelaySeconds: 30
                      periodSeconds: 10
                    readinessProbe:
                      httpGet:
                        path: /health
                        port: 8080
                      initialDelaySeconds: 5
                      periodSeconds: 5

            ---
            # deployments/kubernetes/service.yaml
            apiVersion: v1
            kind: Service
            metadata:
              name: myapp-service
            spec:
              selector:
                app: myapp
              ports:
              - protocol: TCP
                port: 80
                targetPort: 8080
              type: LoadBalancer

            # 部署:
            # $ kubectl apply -f deployments/kubernetes/

02.代码分层
    a.Handler层
        a.完整Handler示例
            // internal/handler/user_handler.go
            package handler

            import (
                "myapp/internal/service"
                "myapp/pkg/response"
                "github.com/gin-gonic/gin"
                "strconv"
            )

            type UserHandler struct {
                userService service.UserService
            }

            func NewUserHandler(userService service.UserService) *UserHandler {
                return &UserHandler{userService: userService}
            }

            // List 获取用户列表
            func (h *UserHandler) List(c *gin.Context) {
                // 参数验证
                page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
                pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))

                if page < 1 || pageSize < 1 || pageSize > 100 {
                    response.Error(c, 400, "无效的分页参数")
                    return
                }

                // 调用Service
                users, total, err := h.userService.GetList(page, pageSize)
                if err != nil {
                    response.Error(c, 500, "查询失败")
                    return
                }

                // 响应封装
                response.SuccessWithPagination(c, users, page, pageSize, total)
            }

            // Get 获取用户详情
            func (h *UserHandler) Get(c *gin.Context) {
                id, err := strconv.Atoi(c.Param("id"))
                if err != nil {
                    response.Error(c, 400, "无效的用户ID")
                    return
                }

                user, err := h.userService.GetByID(id)
                if err != nil {
                    response.Error(c, 404, "用户不存在")
                    return
                }

                response.Success(c, user)
            }

            // Create 创建用户
            func (h *UserHandler) Create(c *gin.Context) {
                var req CreateUserRequest
                if err := c.ShouldBindJSON(&req); err != nil {
                    response.ErrorWithDetails(c, 400, "参数错误", err.Error())
                    return
                }

                user, err := h.userService.Create(req)
                if err != nil {
                    response.Error(c, 500, err.Error())
                    return
                }

                response.Created(c, user)
            }
    b.Service层
        a.完整Service示例
            // internal/service/user_service.go
            package service

            import (
                "errors"
                "myapp/internal/model"
                "myapp/internal/repository"
                "golang.org/x/crypto/bcrypt"
            )

            type UserService interface {
                GetList(page, pageSize int) ([]model.User, int64, error)
                GetByID(id int) (*model.User, error)
                Create(req model.CreateUserRequest) (*model.User, error)
                Update(id int, req model.UpdateUserRequest) error
                Delete(id int) error
            }

            type userService struct {
                userRepo repository.UserRepository
            }

            func NewUserService(userRepo repository.UserRepository) UserService {
                return &userService{userRepo: userRepo}
            }

            func (s *userService) GetList(page, pageSize int) ([]model.User, int64, error) {
                offset := (page - 1) * pageSize
                return s.userRepo.FindAll(offset, pageSize)
            }

            func (s *userService) GetByID(id int) (*model.User, error) {
                return s.userRepo.FindByID(id)
            }

            func (s *userService) Create(req model.CreateUserRequest) (*model.User, error) {
                // 业务逻辑验证
                exists, err := s.userRepo.ExistsByUsername(req.Username)
                if err != nil {
                    return nil, err
                }
                if exists {
                    return nil, errors.New("用户名已存在")
                }

                // 密码加密
                hashedPassword, err := bcrypt.GenerateFromPassword(
                    []byte(req.Password),
                    bcrypt.DefaultCost,
                )
                if err != nil {
                    return nil, err
                }

                // 创建用户实体
                user := &model.User{
                    Username: req.Username,
                    Email:    req.Email,
                    Password: string(hashedPassword),
                }

                // 保存到数据库
                if err := s.userRepo.Create(user); err != nil {
                    return nil, err
                }

                return user, nil
            }

            func (s *userService) Update(id int, req model.UpdateUserRequest) error {
                // 检查用户是否存在
                user, err := s.userRepo.FindByID(id)
                if err != nil {
                    return errors.New("用户不存在")
                }
s
                // 更新字段
                if req.Username != "" {
                    user.Username = req.Username
                }
                if req.Email != "" {
                    user.Email = req.Email
                }
                if req.Age > 0 {
                    user.Age = req.Age
                }

                return s.userRepo.Update(user)
            }

            func (s *userService) Delete(id int) error {
                return s.userRepo.Delete(id)
            }
    c.Repository层
        a.完整Repository示例
            // internal/repository/user_repository.go
            package repository

            import (
                "myapp/internal/model"
                "gorm.io/gorm"
            )

            type UserRepository interface {
                Create(user *model.User) error
                FindByID(id int) (*model.User, error)
                FindAll(offset, limit int) ([]model.User, int64, error)
                Update(user *model.User) error
                Delete(id int) error
                ExistsByUsername(username string) (bool, error)
                ExistsByEmail(email string) (bool, error)
            }

            type userRepository struct {
                db *gorm.DB
            }

            func NewUserRepository(db *gorm.DB) UserRepository {
                return &userRepository{db: db}
            }

            func (r *userRepository) Create(user *model.User) error {
                return r.db.Create(user).Error
            }

            func (r *userRepository) FindByID(id int) (*model.User, error) {
                var user model.User
                err := r.db.First(&user, id).Error
                if err != nil {
                    return nil, err
                }
                return &user, nil
            }

            func (r *userRepository) FindAll(offset, limit int) ([]model.User, int64, error) {
                var users []model.User
                var total int64

                // 查询总数
                if err := r.db.Model(&model.User{}).Count(&total).Error; err != nil {
                    return nil, 0, err
                }

                // 分页查询
                err := r.db.Offset(offset).Limit(limit).Find(&users).Error
                return users, total, err
            }

            func (r *userRepository) Update(user *model.User) error {
                return r.db.Save(user).Error
            }

            func (r *userRepository) Delete(id int) error {
                return r.db.Delete(&model.User{}, id).Error
            }

            func (r *userRepository) ExistsByUsername(username string) (bool, error) {
                var count int64
                err := r.db.Model(&model.User{}).
                    Where("username = ?", username).
                    Count(&count).Error
                return count > 0, err
            }

            func (r *userRepository) ExistsByEmail(email string) (bool, error) {
                var count int64
                err := r.db.Model(&model.User{}).
                    Where("email = ?", email).
                    Count(&count).Error
                return count > 0, err
            }
    d.Model层
        a.完整Model示例
            // internal/model/user.go
            package model

            import (
                "time"
                "gorm.io/gorm"
            )

            // User 用户实体
            type User struct {
                ID        uint           `gorm:"primaryKey" json:"id"`
                Username  string         `gorm:"uniqueIndex;size:50;not null" json:"username"`
                Email     string         `gorm:"uniqueIndex;size:100;not null" json:"email"`
                Password  string         `gorm:"size:255;not null" json:"-"`
                Age       int            `gorm:"default:0" json:"age"`
                Status    int            `gorm:"default:1" json:"status"`
                CreatedAt time.Time      `json:"created_at"`
                UpdatedAt time.Time      `json:"updated_at"`
                DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
            }

            // TableName 指定表名
            func (User) TableName() string {
                return "users"
            }

            // CreateUserRequest DTO - 创建用户请求
            type CreateUserRequest struct {
                Username string `json:"username" binding:"required,min=3,max=20,alphanum"`
                Email    string `json:"email" binding:"required,email"`
                Password string `json:"password" binding:"required,min=6,max=20"`
            }

            // UpdateUserRequest DTO - 更新用户请求
            type UpdateUserRequest struct {
                Username string `json:"username" binding:"omitempty,min=3,max=20,alphanum"`
                Email    string `json:"email" binding:"omitempty,email"`
                Age      int    `json:"age" binding:"omitempty,gte=0,lte=120"`
            }

            // UserVO VO - 用户视图对象(返回给前端)
            type UserVO struct {
                ID        uint      `json:"id"`
                Username  string    `json:"username"`
                Email     string    `json:"email"`
                Age       int       `json:"age"`
                Status    int       `json:"status"`
                CreatedAt time.Time `json:"created_at"`
            }

            // ToVO 转换为VO
            func (u *User) ToVO() *UserVO {
                return &UserVO{
                    ID:        u.ID,
                    Username:  u.Username,
                    Email:     u.Email,
                    Age:       u.Age,
                    Status:    u.Status,
                    CreatedAt: u.CreatedAt,
                }
            }

03.配置管理
    a.配置文件
        a.完整配置示例
            // configs/config.yaml
            app:
              name: myapp
              version: 1.0.0
              env: production

            server:
              host: 0.0.0.0
              port: 8080
              mode: release
              read_timeout: 60
              write_timeout: 60
              max_header_bytes: 1048576

            database:
              driver: mysql
              host: ${DB_HOST:localhost}
              port: ${DB_PORT:3306}
              database: ${DB_NAME:myapp}
              username: ${DB_USER:root}
              password: ${DB_PASSWORD:secret}
              charset: utf8mb4
              parse_time: true
              loc: Local
              max_idle_conns: 10
              max_open_conns: 100
              conn_max_lifetime: 3600

            redis:
              host: ${REDIS_HOST:localhost}
              port: ${REDIS_PORT:6379}
              password: ${REDIS_PASSWORD:}
              db: 0
              pool_size: 10
              min_idle_conns: 5

            log:
              level: info
              format: json
              output: stdout
              file: logs/app.log
              max_size: 100
              max_backups: 7
              max_age: 30
              compress: true

            jwt:
              secret: ${JWT_SECRET:your-secret-key}
              expire: 24h
              refresh_expire: 168h
    b.配置加载
        a.Viper配置加载
            // internal/config/config.go
            package config

            import (
                "fmt"
                "strings"
                "github.com/spf13/viper"
            )

            type Config struct {
                App      AppConfig      `mapstructure:"app"`
                Server   ServerConfig   `mapstructure:"server"`
                Database DatabaseConfig `mapstructure:"database"`
                Redis    RedisConfig    `mapstructure:"redis"`
                Log      LogConfig      `mapstructure:"log"`
                JWT      JWTConfig      `mapstructure:"jwt"`
            }

            func Load() (*Config, error) {
                // 设置配置文件
                viper.SetConfigName("config")
                viper.SetConfigType("yaml")
                viper.AddConfigPath("./configs")
                viper.AddConfigPath(".")

                // 环境变量支持
                viper.AutomaticEnv()
                viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))

                // 读取配置文件
                if err := viper.ReadInConfig(); err != nil {
                    return nil, fmt.Errorf("读取配置文件失败: %w", err)
                }

                // 解析配置
                var config Config
                if err := viper.Unmarshal(&config); err != nil {
                    return nil, fmt.Errorf("解析配置失败: %w", err)
                }

                // 验证配置
                if err := config.Validate(); err != nil {
                    return nil, fmt.Errorf("配置验证失败: %w", err)
                }

                return &config, nil
            }
    c.配置验证
        a.配置验证逻辑
            // Validate 验证配置
            func (c *Config) Validate() error {
                // 验证服务器配置
                if c.Server.Port < 1 || c.Server.Port > 65535 {
                    return fmt.Errorf("无效的端口号: %d", c.Server.Port)
                }

                // 验证数据库配置
                if c.Database.Host == "" {
                    return fmt.Errorf("数据库主机不能为空")
                }
                if c.Database.Database == "" {
                    return fmt.Errorf("数据库名称不能为空")
                }

                // 验证Redis配置
                if c.Redis.Host == "" {
                    return fmt.Errorf("Redis主机不能为空")
                }

                // 验证JWT配置
                if c.JWT.Secret == "" || c.JWT.Secret == "your-secret-key" {
                    return fmt.Errorf("JWT密钥未设置或使用默认值")
                }

                return nil
            }
    d.配置热更新
        a.热更新实现
            // WatchConfig 监听配置变化
            func WatchConfig(onChange func(*Config)) {
                viper.WatchConfig()
                viper.OnConfigChange(func(e fsnotify.Event) {
                    log.Printf("配置文件已更改: %s", e.Name)

                    var newConfig Config
                    if err := viper.Unmarshal(&newConfig); err != nil {
                        log.Printf("重新加载配置失败: %v", err)
                        return
                    }

                    if err := newConfig.Validate(); err != nil {
                        log.Printf("新配置验证失败: %v", err)
                        return
                    }

                    // 触发回调
                    if onChange != nil {
                        onChange(&newConfig)
                    }
                })
            }

            // 使用示例
            func main() {
                cfg, _ := config.Load()

                // 启用热更新
                config.WatchConfig(func(newCfg *config.Config) {
                    log.Println("配置已更新,重新初始化...")
                    // 这里可以重新初始化某些组件
                })

                // 启动应用...
            }

04.依赖管理
    a.go.mod
        a.模块管理
            // go.mod
            module myapp

            go 1.21

            require (
                github.com/gin-gonic/gin v1.9.1
                github.com/spf13/viper v1.16.0
                gorm.io/gorm v1.25.4
                gorm.io/driver/mysql v1.5.1
                github.com/go-redis/redis/v8 v8.11.5
                go.uber.org/zap v1.25.0
                github.com/google/wire v0.5.0
                golang.org/x/crypto v0.14.0
            )

            require (
                github.com/gin-contrib/sse v0.1.0 // indirect
                github.com/go-playground/validator/v10 v10.15.5 // indirect
                // ... 其他间接依赖
            )

            // replace指令 - 用于本地开发或替换依赖
            // replace github.com/some/package => ../local/package
            // replace github.com/some/package => github.com/fork/package v1.2.3

            // 常用命令:
            // $ go mod init myapp              # 初始化模块
            // $ go mod tidy                    # 整理依赖
            // $ go mod download                # 下载依赖
            // $ go mod vendor                  # 创建vendor目录
            // $ go mod verify                  # 验证依赖
            // $ go get -u ./...                # 更新所有依赖
            // $ go get github.com/[email protected]   # 安装指定版本
    b.依赖注入
        a.Wire完整示例
            // internal/wire/wire.go
            //go:build wireinject
            // +build wireinject

            package wire

            import (
                "myapp/internal/config"
                "myapp/internal/handler"
                "myapp/internal/service"
                "myapp/internal/repository"
                "github.com/google/wire"
                "gorm.io/gorm"
            )

            func InitializeApp(cfg *config.Config) (*App, func(), error) {
                wire.Build(
                    // 基础设施
                    NewDB,
                    NewRedis,
                    NewLogger,

                    // Repository
                    repository.NewUserRepository,
                    repository.NewPostRepository,

                    // Service
                    service.NewUserService,
                    service.NewPostService,

                    // Handler
                    handler.NewUserHandler,
                    handler.NewPostHandler,

                    // App
                    NewApp,
                )
                return &App{}, nil, nil
            }

            // NewDB 创建数据库连接
            func NewDB(cfg *config.Config) (*gorm.DB, func(), error) {
                dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=True&loc=Local",
                    cfg.Database.Username,
                    cfg.Database.Password,
                    cfg.Database.Host,
                    cfg.Database.Port,
                    cfg.Database.Database,
                    cfg.Database.Charset,
                )

                db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
                if err != nil {
                    return nil, nil, err
                }

                sqlDB, _ := db.DB()
                sqlDB.SetMaxIdleConns(cfg.Database.MaxIdleConns)
                sqlDB.SetMaxOpenConns(cfg.Database.MaxOpenConns)

                cleanup := func() {
                    sqlDB.Close()
                }

                return db, cleanup, nil
            }

            // 生成Wire代码:
            // $ wire gen ./internal/wire
    c.初始化
        a.应用初始化
            // cmd/server/main.go
            func main() {
                // 1. 加载配置
                cfg, err := config.Load()
                if err != nil {
                    log.Fatal("加载配置失败:", err)
                }

                // 2. 初始化日志
                logger := initLogger(cfg)
                defer logger.Sync()

                // 3. 初始化应用(Wire依赖注入)
                app, cleanup, err := wire.InitializeApp(cfg)
                if err != nil {
                    logger.Fatal("初始化应用失败", zap.Error(err))
                }
                defer cleanup()

                // 4. 数据库迁移
                if err := runMigrations(app.DB); err != nil {
                    logger.Fatal("数据库迁移失败", zap.Error(err))
                }

                // 5. 启动定时任务
                startCronJobs(app)

                // 6. 创建HTTP服务器
                srv := &http.Server{
                    Addr:    ":" + cfg.Server.Port,
                    Handler: app.Router,
                }

                // 7. 启动服务器
                go func() {
                    logger.Info("服务器启动", zap.String("addr", srv.Addr))
                    if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
                        logger.Fatal("服务器启动失败", zap.Error(err))
                    }
                }()

                // 8. 优雅关闭
                gracefulShutdown(srv, cleanup, logger)
            }
    d.优雅关闭
        a.完整优雅关闭
            func gracefulShutdown(srv *http.Server, cleanup func(), logger *zap.Logger) {
                // 监听系统信号
                quit := make(chan os.Signal, 1)
                signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
                <-quit

                logger.Info("正在关闭服务器...")

                // 设置超时上下文
                ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
                defer cancel()

                // 关闭HTTP服务器
                if err := srv.Shutdown(ctx); err != nil {
                    logger.Error("服务器强制关闭", zap.Error(err))
                }

                // 清理资源
                logger.Info("正在清理资源...")
                cleanup()

                // 等待所有goroutine完成
                select {
                case <-ctx.Done():
                    logger.Warn("清理超时")
                default:
                    logger.Info("服务器已安全退出")
                }
            }

            // 资源清理示例
            func cleanup() {
                // 关闭数据库连接
                if db != nil {
                    sqlDB, _ := db.DB()
                    sqlDB.Close()
                    log.Println("数据库连接已关闭")
                }

                // 关闭Redis连接
                if redisClient != nil {
                    redisClient.Close()
                    log.Println("Redis连接已关闭")
                }

                // 停止定时任务
                if cronScheduler != nil {
                    cronScheduler.Stop()
                    log.Println("定时任务已停止")
                }

                // 刷新日志
                if logger != nil {
                    logger.Sync()
                }
            }

2 路由系统

2.1 汇总:6个

01.基础路由
    HTTP方法路由、路径定义、处理函数

02.路由参数
    路径参数、查询参数、通配符

03.路由分组
    Group方法、中间件共享、版本管理

04.动态路由
    参数路由、正则匹配、优先级

05.路由优先级
    精确匹配、参数匹配、通配符

06.路由中间件
    分组中间件、路由级中间件、执行顺序

2.2 基础路由

01.HTTP方法
    a.GET方法
        a.方法定义
            a.路由注册和使用场景
                // 基础GET路由
                router.GET("/", func(c *gin.Context) {
                    c.JSON(200, gin.H{"message": "Welcome"})
                })

                // 获取列表
                router.GET("/users", func(c *gin.Context) {
                    // 获取分页参数
                    page := c.DefaultQuery("page", "1")
                    pageSize := c.DefaultQuery("page_size", "10")

                    users := getUserList(page, pageSize)
                    c.JSON(200, gin.H{
                        "code": 0,
                        "data": users,
                    })
                })

                // 获取详情
                router.GET("/users/:id", func(c *gin.Context) {
                    id := c.Param("id")
                    user := getUserByID(id)

                    if user == nil {
                        c.JSON(404, gin.H{"error": "用户不存在"})
                        return
                    }

                    c.JSON(200, gin.H{
                        "code": 0,
                        "data": user,
                    })
                })

                // 请求:GET /users?page=1&page_size=20
                // 请求:GET /users/123
        b.方法特性
            a.幂等性和缓存
                // GET方法特性:
                // 1. 幂等:多次请求结果相同
                // 2. 安全:不改变服务器状态
                // 3. 可缓存:支持HTTP缓存机制

                // 使用ETag缓存
                router.GET("/api/data", func(c *gin.Context) {
                    data := getData()

                    // 计算ETag
                    etag := calculateETag(data)

                    // 检查客户端ETag
                    if c.GetHeader("If-None-Match") == etag {
                        c.Status(304) // Not Modified
                        return
                    }

                    // 设置ETag头
                    c.Header("ETag", etag)
                    c.Header("Cache-Control", "max-age=3600")
                    c.JSON(200, data)
                })

                // 使用Last-Modified
                router.GET("/api/resource", func(c *gin.Context) {
                    resource := getResource()
                    lastModified := resource.UpdatedAt

                    // 检查If-Modified-Since
                    if ifModifiedSince := c.GetHeader("If-Modified-Since"); ifModifiedSince != "" {
                        clientTime, _ := time.Parse(time.RFC1123, ifModifiedSince)
                        if !lastModified.After(clientTime) {
                            c.Status(304)
                            return
                        }
                    }

                    c.Header("Last-Modified", lastModified.Format(time.RFC1123))
                    c.JSON(200, resource)
                })
    b.POST方法
        a.方法定义
            a.创建资源
                // 创建用户
                router.POST("/users", func(c *gin.Context) {
                    var user User

                    // 绑定JSON数据
                    if err := c.ShouldBindJSON(&user); err != nil {
                        c.JSON(400, gin.H{"error": err.Error()})
                        return
                    }

                    // 验证数据
                    if user.Username == "" || user.Email == "" {
                        c.JSON(400, gin.H{"error": "用户名和邮箱不能为空"})
                        return
                    }

                    // 创建用户
                    if err := createUser(&user); err != nil {
                        c.JSON(500, gin.H{"error": "创建失败"})
                        return
                    }

                    // 返回201 Created
                    c.JSON(201, gin.H{
                        "code": 0,
                        "message": "创建成功",
                        "data": user,
                    })
                })

                // 请求示例:
                // POST /users
                // Content-Type: application/json
                // {
                //   "username": "alice",
                //   "email": "[email protected]",
                //   "password": "secret123"
                // }
        b.方法特性
            a.非幂等性和请求体
                // POST方法特性:
                // 1. 非幂等:每次请求可能创建新资源
                // 2. 不安全:改变服务器状态
                // 3. 不可缓存:响应不应被缓存

                // 处理表单数据
                router.POST("/upload", func(c *gin.Context) {
                    // 获取表单字段
                    title := c.PostForm("title")
                    description := c.PostForm("description")

                    // 获取上传文件
                    file, err := c.FormFile("file")
                    if err != nil {
                        c.JSON(400, gin.H{"error": "文件上传失败"})
                        return
                    }

                    // 保存文件
                    filename := filepath.Base(file.Filename)
                    if err := c.SaveUploadedFile(file, "./uploads/"+filename); err != nil {
                        c.JSON(500, gin.H{"error": "保存失败"})
                        return
                    }

                    c.JSON(201, gin.H{
                        "title": title,
                        "filename": filename,
                        "size": file.Size,
                    })
                })

                // 处理大数据
                router.POST("/batch", func(c *gin.Context) {
                    var items []Item

                    if err := c.ShouldBindJSON(&items); err != nil {
                        c.JSON(400, gin.H{"error": err.Error()})
                        return
                    }

                    // 批量创建
                    result := batchCreate(items)
                    c.JSON(201, result)
                })
    c.PUT方法
        a.方法定义
            a.完整更新资源
                // 更新用户(完整替换)
                router.PUT("/users/:id", func(c *gin.Context) {
                    id := c.Param("id")

                    var user User
                    if err := c.ShouldBindJSON(&user); err != nil {
                        c.JSON(400, gin.H{"error": err.Error()})
                        return
                    }

                    // 检查用户是否存在
                    existingUser := getUserByID(id)
                    if existingUser == nil {
                        c.JSON(404, gin.H{"error": "用户不存在"})
                        return
                    }

                    // 完整更新(替换所有字段)
                    user.ID = existingUser.ID
                    if err := updateUser(&user); err != nil {
                        c.JSON(500, gin.H{"error": "更新失败"})
                        return
                    }

                    c.JSON(200, gin.H{
                        "code": 0,
                        "message": "更新成功",
                        "data": user,
                    })
                })

                // 请求示例:
                // PUT /users/123
                // {
                //   "username": "alice",
                //   "email": "[email protected]",
                //   "age": 25,
                //   "status": 1
                // }
                // 注意:需要提供所有字段,未提供的字段会被设为零值
        b.方法特性
            a.幂等性和完整更新
                // PUT vs PATCH

                // PUT:完整替换资源
                router.PUT("/users/:id", func(c *gin.Context) {
                    var user User
                    c.ShouldBindJSON(&user)

                    // 替换整个资源
                    user.ID = c.Param("id")
                    updateUser(&user)

                    c.JSON(200, user)
                })

                // PATCH:部分更新资源
                router.PATCH("/users/:id", func(c *gin.Context) {
                    id := c.Param("id")

                    var updates map[string]interface{}
                    c.ShouldBindJSON(&updates)

                    // 只更新提供的字段
                    partialUpdateUser(id, updates)

                    c.JSON(200, gin.H{"message": "部分更新成功"})
                })

                // PUT幂等性示例
                router.PUT("/config/:key", func(c *gin.Context) {
                    key := c.Param("key")
                    var value ConfigValue
                    c.ShouldBindJSON(&value)

                    // 多次执行结果相同
                    setConfig(key, value)

                    c.JSON(200, gin.H{
                        "key": key,
                        "value": value,
                    })
                })
    d.DELETE方法
        a.方法定义
            a.删除资源
                // 删除用户
                router.DELETE("/users/:id", func(c *gin.Context) {
                    id := c.Param("id")

                    // 检查用户是否存在
                    user := getUserByID(id)
                    if user == nil {
                        // 资源不存在也返回成功(幂等性)
                        c.JSON(200, gin.H{
                            "code": 0,
                            "message": "删除成功",
                        })
                        return
                    }

                    // 权限检查
                    currentUserID := c.GetInt("user_id")
                    if !canDelete(currentUserID, id) {
                        c.JSON(403, gin.H{"error": "无权删除"})
                        return
                    }

                    // 删除用户
                    if err := deleteUser(id); err != nil {
                        c.JSON(500, gin.H{"error": "删除失败"})
                        return
                    }

                    // 返回204 No Content 或 200 OK
                    c.Status(204)
                })

                // 请求:DELETE /users/123
        b.方法特性
            a.幂等性和软删除
                // 物理删除
                router.DELETE("/users/:id", func(c *gin.Context) {
                    id := c.Param("id")

                    // 永久删除
                    db.Unscoped().Delete(&User{}, id)

                    c.Status(204)
                })

                // 软删除(逻辑删除)
                router.DELETE("/users/:id/soft", func(c *gin.Context) {
                    id := c.Param("id")

                    // 标记删除(设置deleted_at字段)
                    db.Delete(&User{}, id)

                    c.JSON(200, gin.H{
                        "code": 0,
                        "message": "已移至回收站",
                    })
                })

                // 批量删除
                router.DELETE("/users", func(c *gin.Context) {
                    var ids []int
                    if err := c.ShouldBindJSON(&ids); err != nil {
                        c.JSON(400, gin.H{"error": err.Error()})
                        return
                    }

                    // 批量删除
                    result := db.Delete(&User{}, ids)

                    c.JSON(200, gin.H{
                        "code": 0,
                        "deleted_count": result.RowsAffected,
                    })
                })

                // 请求示例:
                // DELETE /users
                // [1, 2, 3, 4, 5]

02.路径定义
    a.静态路径
        a.精确匹配
            // 静态路径示例
            router.GET("/users", listUsers)
            router.GET("/api/v1/products", listProducts)
            router.GET("/about", aboutPage)

            // 特点:
            // - 精确匹配,不会匹配 /users/123
            // - 优先级最高
            // - 性能最好

            // 完整示例
            router.GET("/", func(c *gin.Context) {
                c.HTML(200, "index.html", nil)
            })

            router.GET("/users", func(c *gin.Context) {
                users := []string{"Alice", "Bob", "Charlie"}
                c.JSON(200, gin.H{"users": users})
            })

            router.GET("/api/v1/products", func(c *gin.Context) {
                c.JSON(200, gin.H{"products": []string{"Product1", "Product2"}})
            })
    b.根路径
        a.首页处理
            // 根路径路由
            router.GET("/", func(c *gin.Context) {
                c.HTML(200, "index.html", gin.H{
                    "title": "欢迎页面",
                })
            })

            // 或返回JSON
            router.GET("/", func(c *gin.Context) {
                c.JSON(200, gin.H{
                    "message": "Welcome to API",
                    "version": "1.0.0",
                    "endpoints": []string{
                        "/api/v1/users",
                        "/api/v1/products",
                    },
                })
            })
    c.路径规则
        a.大小写敏感
            // Gin路径区分大小写
            router.GET("/Users", handler1)  // 不同于
            router.GET("/users", handler2)  // 这个路由

            // 请求:
            // GET /Users  -> handler1
            // GET /users  -> handler2
            // GET /USERS  -> 404
        b.尾部斜杠处理
            // 尾部斜杠不会自动重定向
            router.GET("/users", handler1)
            router.GET("/users/", handler2)  // 这是不同的路由

            // 如需统一处理,可以注册两个路由
            handler := func(c *gin.Context) {
                c.JSON(200, gin.H{"message": "users"})
            }
            router.GET("/users", handler)
            router.GET("/users/", handler)

            // 或使用中间件自动重定向
            func RedirectTrailingSlash() gin.HandlerFunc {
                return func(c *gin.Context) {
                    path := c.Request.URL.Path
                    if len(path) > 1 && path[len(path)-1] == '/' {
                        c.Redirect(301, path[:len(path)-1])
                        c.Abort()
                    }
                }
            }
    d.路径冲突
        a.冲突检测
            // 以下会产生冲突(编译时报错)
            router.GET("/users/:id", handler1)
            router.GET("/users/:name", handler2)  // 错误!参数名不同但路径相同

            // 正确做法:
            router.GET("/users/:id", func(c *gin.Context) {
                id := c.Param("id")
                // 根据id格式判断
                if isNumeric(id) {
                    // 处理数字ID
                } else {
                    // 处理用户名
                }
            })

            // 或使用不同路径
            router.GET("/users/id/:id", getUserByID)
            router.GET("/users/name/:name", getUserByName)

03.处理函数
    a.HandlerFunc
        a.基础处理函数
            // HandlerFunc类型定义
            type HandlerFunc func(*gin.Context)

            // 基础处理函数示例
            func helloHandler(c *gin.Context) {
                // 获取请求信息
                method := c.Request.Method
                path := c.Request.URL.Path

                // 处理业务逻辑
                message := fmt.Sprintf("Hello from %s %s", method, path)

                // 返回响应
                c.JSON(200, gin.H{
                    "message": message,
                    "timestamp": time.Now(),
                })
            }

            // 注册路由
            router.GET("/hello", helloHandler)
            router.POST("/hello", helloHandler)
        b.带参数的处理函数
            // 处理路径参数
            func getUserHandler(c *gin.Context) {
                id := c.Param("id")
                userID, err := strconv.Atoi(id)
                if err != nil {
                    c.JSON(400, gin.H{"error": "无效的用户ID"})
                    return
                }

                // 查询用户
                user := getUserByID(userID)
                if user == nil {
                    c.JSON(404, gin.H{"error": "用户不存在"})
                    return
                }

                c.JSON(200, user)
            }

            router.GET("/users/:id", getUserHandler)
    b.多个处理器
        a.中间件链
            // 认证中间件
            func authMiddleware(c *gin.Context) {
                token := c.GetHeader("Authorization")
                if token == "" {
                    c.JSON(401, gin.H{"error": "未授权"})
                    c.Abort()  // 终止后续处理器
                    return
                }

                // 验证token
                userID, err := validateToken(token)
                if err != nil {
                    c.JSON(401, gin.H{"error": "无效的token"})
                    c.Abort()
                    return
                }

                // 保存用户信息到上下文
                c.Set("user_id", userID)
                c.Next()  // 继续执行下一个处理器
            }

            // 日志中间件
            func loggerMiddleware(c *gin.Context) {
                start := time.Now()
                path := c.Request.URL.Path

                c.Next()  // 先执行后续处理器

                // 记录日志
                latency := time.Since(start)
                status := c.Writer.Status()
                log.Printf("[%d] %s - %v", status, path, latency)
            }

            // 业务处理器
            func businessHandler(c *gin.Context) {
                userID := c.GetInt("user_id")
                c.JSON(200, gin.H{
                    "user_id": userID,
                    "message": "处理成功",
                })
            }

            // 注册多个处理器
            router.GET("/api/data",
                loggerMiddleware,
                authMiddleware,
                businessHandler,
            )
    c.匿名函数
        a.内联定义
            // 简单的匿名函数
            router.GET("/ping", func(c *gin.Context) {
                c.JSON(200, gin.H{"message": "pong"})
            })

            // 带逻辑的匿名函数
            router.POST("/users", func(c *gin.Context) {
                var user User
                if err := c.ShouldBindJSON(&user); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                // 保存用户
                if err := saveUser(&user); err != nil {
                    c.JSON(500, gin.H{"error": "保存失败"})
                    return
                }

                c.JSON(201, user)
            })
        b.闭包使用
            // 使用闭包创建处理器工厂
            func makeAuthHandler(requiredRole string) gin.HandlerFunc {
                return func(c *gin.Context) {
                    userRole := c.GetString("user_role")
                    if userRole != requiredRole {
                        c.JSON(403, gin.H{"error": "权限不足"})
                        c.Abort()
                        return
                    }
                    c.Next()
                }
            }

            // 使用不同权限的处理器
            router.GET("/admin/users", makeAuthHandler("admin"), listUsers)
            router.GET("/manager/reports", makeAuthHandler("manager"), getReports)

            // 闭包捕获外部变量
            counter := 0
            router.GET("/count", func(c *gin.Context) {
                counter++
                c.JSON(200, gin.H{"count": counter})
            })
    d.方法绑定
        a.控制器模式
            // 定义控制器结构体
            type UserController struct {
                userService UserService
            }

            func NewUserController(service UserService) *UserController {
                return &UserController{userService: service}
            }

            // 控制器方法
            func (ctrl *UserController) List(c *gin.Context) {
                users, err := ctrl.userService.GetAll()
                if err != nil {
                    c.JSON(500, gin.H{"error": err.Error()})
                    return
                }
                c.JSON(200, users)
            }

            func (ctrl *UserController) Get(c *gin.Context) {
                id, _ := strconv.Atoi(c.Param("id"))
                user, err := ctrl.userService.GetByID(id)
                if err != nil {
                    c.JSON(404, gin.H{"error": "用户不存在"})
                    return
                }
                c.JSON(200, user)
            }

            func (ctrl *UserController) Create(c *gin.Context) {
                var req CreateUserRequest
                if err := c.ShouldBindJSON(&req); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                user, err := ctrl.userService.Create(req)
                if err != nil {
                    c.JSON(500, gin.H{"error": err.Error()})
                    return
                }
                c.JSON(201, user)
            }

            // 注册路由
            userCtrl := NewUserController(userService)
            router.GET("/users", userCtrl.List)
            router.GET("/users/:id", userCtrl.Get)
            router.POST("/users", userCtrl.Create)

04.路由注册
    a.单个注册
        a.基础注册
            // 逐个注册路由
            router := gin.Default()

            // GET路由
            router.GET("/", homeHandler)
            router.GET("/users", listUsers)
            router.GET("/users/:id", getUser)

            // POST路由
            router.POST("/users", createUser)
            router.POST("/login", loginHandler)

            // PUT路由
            router.PUT("/users/:id", updateUser)

            // DELETE路由
            router.DELETE("/users/:id", deleteUser)

            // 特点:清晰明确,易于理解和维护
    b.批量注册
        a.循环注册
            // 定义路由配置
            type RouteConfig struct {
                Method  string
                Path    string
                Handler gin.HandlerFunc
            }

            routes := []RouteConfig{
                {"GET", "/users", listUsers},
                {"GET", "/users/:id", getUser},
                {"POST", "/users", createUser},
                {"PUT", "/users/:id", updateUser},
                {"DELETE", "/users/:id", deleteUser},
            }

            // 批量注册
            for _, route := range routes {
                router.Handle(route.Method, route.Path, route.Handler)
            }
    c.路由表
        a.集中管理
            // routes/routes.go
            package routes

            type Route struct {
                Method      string
                Path        string
                Handler     gin.HandlerFunc
                Middlewares []gin.HandlerFunc
                Description string
            }

            func GetRoutes() []Route {
                return []Route{
                    {
                        Method:      "GET",
                        Path:        "/api/v1/users",
                        Handler:     handler.ListUsers,
                        Middlewares: []gin.HandlerFunc{middleware.Auth()},
                        Description: "获取用户列表",
                    },
                    {
                        Method:      "POST",
                        Path:        "/api/v1/users",
                        Handler:     handler.CreateUser,
                        Middlewares: []gin.HandlerFunc{middleware.Auth(), middleware.Admin()},
                        Description: "创建用户",
                    },
                }
            }

            // 注册路由
            func RegisterRoutes(router *gin.Engine) {
                for _, route := range GetRoutes() {
                    handlers := append(route.Middlewares, route.Handler)
                    router.Handle(route.Method, route.Path, handlers...)
                }
            }
    d.自动注册
        a.反射注册
            // 使用反射自动注册控制器方法
            func RegisterController(router *gin.Engine, ctrl interface{}, prefix string) {
                v := reflect.ValueOf(ctrl)
                t := reflect.TypeOf(ctrl)

                for i := 0; i < t.NumMethod(); i++ {
                    method := t.Method(i)

                    // 根据方法名推断HTTP方法和路径
                    // 例如:GetUsers -> GET /users
                    //      CreateUser -> POST /user
                    httpMethod, path := parseMethodName(method.Name)

                    // 创建处理函数
                    handler := func(c *gin.Context) {
                        method.Func.Call([]reflect.Value{v, reflect.ValueOf(c)})
                    }

                    router.Handle(httpMethod, prefix+path, handler)
                }
            }

            // 使用
            userCtrl := &UserController{}
            RegisterController(router, userCtrl, "/api/v1")

2.3 路由参数

01.路径参数
    a.定义方式
        a.基础路径参数
            // 单个参数
            router.GET("/users/:id", func(c *gin.Context) {
                id := c.Param("id")
                c.JSON(200, gin.H{"user_id": id})
            })

            // 多个参数
            router.GET("/posts/:category/:id", func(c *gin.Context) {
                category := c.Param("category")
                id := c.Param("id")
                c.JSON(200, gin.H{
                    "category": category,
                    "id": id,
                })
            })

            // 请求:GET /posts/tech/123
            // 响应:{"category": "tech", "id": "123"}
    b.获取参数
        a.参数获取和转换
            router.GET("/users/:id", func(c *gin.Context) {
                // 获取字符串参数
                idStr := c.Param("id")

                // 转换为整数
                id, err := strconv.Atoi(idStr)
                if err != nil {
                    c.JSON(400, gin.H{"error": "无效的ID"})
                    return
                }

                // 验证范围
                if id < 1 || id > 10000 {
                    c.JSON(400, gin.H{"error": "ID超出范围"})
                    return
                }

                user := getUserByID(id)
                c.JSON(200, user)
            })

02.查询参数
    a.获取方式
        a.基础查询参数
            router.GET("/search", func(c *gin.Context) {
                // 获取参数(可能为空)
                keyword := c.Query("keyword")

                // 获取参数(带默认值)
                page := c.DefaultQuery("page", "1")
                pageSize := c.DefaultQuery("page_size", "10")

                // 检查参数是否存在
                sort, exists := c.GetQuery("sort")
                if !exists {
                    sort = "created_at"
                }

                c.JSON(200, gin.H{
                    "keyword": keyword,
                    "page": page,
                    "page_size": pageSize,
                    "sort": sort,
                })
            })

            // 请求:GET /search?keyword=golang&page=2&sort=name
    b.多值参数
        a.数组参数
            router.GET("/filter", func(c *gin.Context) {
                // 获取数组参数
                tags := c.QueryArray("tags")
                ids, exists := c.GetQueryArray("ids")

                c.JSON(200, gin.H{
                    "tags": tags,
                    "ids": ids,
                    "has_ids": exists,
                })
            })

            // 请求:GET /filter?tags=go&tags=web&ids=1&ids=2&ids=3
            // 响应:{"tags": ["go", "web"], "ids": ["1", "2", "3"], "has_ids": true}

03.通配符路由
    a.星号通配
        a.文件服务
            // 静态文件服务
            router.GET("/static/*filepath", func(c *gin.Context) {
                filepath := c.Param("filepath")

                // 安全检查:防止路径遍历攻击
                if strings.Contains(filepath, "..") {
                    c.JSON(403, gin.H{"error": "禁止访问"})
                    return
                }

                // 提供文件
                c.File("./public" + filepath)
            })

            // 请求:GET /static/css/main.css
            // filepath = "/css/main.css"

            // 或使用Gin内置方法
            router.Static("/static", "./public")
            router.StaticFile("/favicon.ico", "./public/favicon.ico")
    d.使用场景
        a.SPA路由
            // 单页应用路由(所有路径返回index.html)
            router.NoRoute(func(c *gin.Context) {
                // API路径返回404
                if strings.HasPrefix(c.Request.URL.Path, "/api/") {
                    c.JSON(404, gin.H{"error": "接口不存在"})
                    return
                }

                // 其他路径返回index.html(由前端路由处理)
                c.File("./dist/index.html")
            })

04.参数验证
    a.必填验证
        a.基础验证
            // 定义验证结构体
            type CreateUserRequest struct {
                Username string `json:"username" binding:"required"`
                Email    string `json:"email" binding:"required,email"`
                Password string `json:"password" binding:"required,min=6"`
                Age      int    `json:"age" binding:"required,gte=0,lte=120"`
            }

            router.POST("/users", func(c *gin.Context) {
                var req CreateUserRequest

                if err := c.ShouldBindJSON(&req); err != nil {
                    c.JSON(400, gin.H{
                        "error": "参数验证失败",
                        "details": err.Error(),
                    })
                    return
                }

                c.JSON(201, gin.H{"message": "创建成功"})
            })
    b.格式验证
        a.常用格式
            type UserProfile struct {
                Email    string `json:"email" binding:"required,email"`
                Website  string `json:"website" binding:"omitempty,url"`
                Phone    string `json:"phone" binding:"required,len=11"`
                Username string `json:"username" binding:"required,alphanum,min=3,max=20"`
            }

            // 自定义正则验证
            type CustomValidation struct {
                Code string `json:"code" binding:"required,regexp=^[A-Z]{2}[0-9]{6}$"`
            }
    c.范围验证
        a.数值和长度
            type ProductRequest struct {
                Name     string   `json:"name" binding:"required,min=2,max=100"`
                Price    float64  `json:"price" binding:"required,gt=0,lte=999999"`
                Stock    int      `json:"stock" binding:"gte=0"`
                Category string   `json:"category" binding:"required,oneof=electronics books clothing"`
                Tags     []string `json:"tags" binding:"required,min=1,max=10,dive,min=2,max=20"`
            }
    d.自定义验证
        a.注册自定义验证器
            import "github.com/go-playground/validator/v10"

            // 自定义验证函数
            func validateUsername(fl validator.FieldLevel) bool {
                username := fl.Field().String()
                // 用户名不能包含特殊字符
                return !strings.ContainsAny(username, "!@#$%^&*()")
            }

            // 注册验证器
            if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
                v.RegisterValidation("username", validateUsername)
            }

            // 使用
            type User struct {
                Username string `json:"username" binding:"required,username"`
            }

2.4 路由分组

01.Group方法
    a.基础用法
        a.基础分组
            // 创建路由分组
            v1 := router.Group("/api/v1")
            {
                v1.GET("/users", listUsers)
                v1.POST("/users", createUser)
                v1.GET("/users/:id", getUser)
                v1.PUT("/users/:id", updateUser)
                v1.DELETE("/users/:id", deleteUser)
            }

            // 访问:GET /api/v1/users
    b.嵌套分组
        a.多层嵌套
            // API版本分组
            api := router.Group("/api")
            {
                v1 := api.Group("/v1")
                {
                    // 用户模块
                    users := v1.Group("/users")
                    {
                        users.GET("", listUsers)
                        users.POST("", createUser)
                        users.GET("/:id", getUser)
                    }

                    // 管理员模块
                    admin := v1.Group("/admin")
                    admin.Use(authMiddleware, adminMiddleware)
                    {
                        admin.GET("/users", adminListUsers)
                        admin.DELETE("/users/:id", adminDeleteUser)
                    }
                }

                v2 := api.Group("/v2")
                {
                    v2.GET("/users", listUsersV2)
                }
            }

            // 访问:GET /api/v1/admin/users
    c.分组配置
        a.中间件共享
            // 为分组添加中间件
            authorized := router.Group("/api")
            authorized.Use(authMiddleware())
            {
                authorized.POST("/submit", submitHandler)
                authorized.POST("/read", readHandler)
            }

            // 多个中间件
            admin := router.Group("/admin")
            admin.Use(authMiddleware(), loggerMiddleware(), adminMiddleware())
            {
                admin.GET("/dashboard", dashboardHandler)
                admin.POST("/settings", settingsHandler)
            }

02.版本管理
    a.URL版本
        a.路径版本控制
            // API v1
            v1 := router.Group("/api/v1")
            {
                v1.GET("/users", func(c *gin.Context) {
                    c.JSON(200, gin.H{"version": "v1", "users": getUsersV1()})
                })
            }

            // API v2
            v2 := router.Group("/api/v2")
            {
                v2.GET("/users", func(c *gin.Context) {
                    c.JSON(200, gin.H{"version": "v2", "users": getUsersV2()})
                })
            }

            // 访问:GET /api/v1/users 或 GET /api/v2/users
    b.Header版本
        a.基于Header的版本控制
            func VersionMiddleware() gin.HandlerFunc {
                return func(c *gin.Context) {
                    version := c.GetHeader("Accept-Version")
                    if version == "" {
                        version = "v1" // 默认版本
                    }
                    c.Set("api_version", version)
                    c.Next()
                }
            }

            router.Use(VersionMiddleware())

            router.GET("/api/users", func(c *gin.Context) {
                version := c.GetString("api_version")

                switch version {
                case "v2":
                    c.JSON(200, getUsersV2())
                default:
                    c.JSON(200, getUsersV1())
                }
            })
    c.版本策略
        a.废弃通知
            // 标记废弃的API
            v1.GET("/old-endpoint", func(c *gin.Context) {
                c.Header("Warning", "299 - \"Deprecated API\"")
                c.Header("Sunset", "Sat, 31 Dec 2024 23:59:59 GMT")
                c.JSON(200, gin.H{
                    "message": "此API将在2024年12月31日废弃",
                    "deprecated": true,
                    "migration_guide": "/api/v2/new-endpoint",
                })
            })

03.模块分组
    a.功能模块
        a.模块化路由
            // 用户模块
            userGroup := router.Group("/api/users")
            {
                userGroup.GET("", listUsers)
                userGroup.POST("", createUser)
                userGroup.GET("/:id", getUser)
                userGroup.PUT("/:id", updateUser)
                userGroup.DELETE("/:id", deleteUser)
            }

            // 订单模块
            orderGroup := router.Group("/api/orders")
            {
                orderGroup.GET("", listOrders)
                orderGroup.POST("", createOrder)
                orderGroup.GET("/:id", getOrder)
            }

            // 商品模块
            productGroup := router.Group("/api/products")
            {
                productGroup.GET("", listProducts)
                productGroup.POST("", createProduct)
            }
    b.权限分组
        a.分级权限控制
            // 公开接口(无需认证)
            public := router.Group("/api/public")
            {
                public.GET("/products", listPublicProducts)
                public.GET("/articles", listArticles)
            }

            // 认证接口(需要登录)
            auth := router.Group("/api")
            auth.Use(AuthMiddleware())
            {
                auth.GET("/profile", getProfile)
                auth.POST("/orders", createOrder)
            }

            // 管理接口(需要管理员权限)
            admin := router.Group("/api/admin")
            admin.Use(AuthMiddleware(), AdminMiddleware())
            {
                admin.GET("/users", adminListUsers)
                admin.DELETE("/users/:id", adminDeleteUser)
            }

04.中间件共享
    a.分组中间件
        a.中间件应用
            // 全局中间件
            router.Use(LoggerMiddleware())
            router.Use(RecoveryMiddleware())

            // 分组中间件
            api := router.Group("/api")
            api.Use(CORSMiddleware())
            {
                // 认证分组
                auth := api.Group("/auth")
                auth.Use(AuthMiddleware())
                {
                    auth.GET("/profile", getProfile)
                    auth.POST("/logout", logout)
                }

                // 管理员分组
                admin := api.Group("/admin")
                admin.Use(AuthMiddleware(), AdminMiddleware(), AuditMiddleware())
                {
                    admin.GET("/users", adminListUsers)
                }
            }
    b.公共逻辑
        a.常用中间件组合
            // CORS中间件
            func CORSMiddleware() gin.HandlerFunc {
                return func(c *gin.Context) {
                    c.Header("Access-Control-Allow-Origin", "*")
                    c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
                    c.Header("Access-Control-Allow-Headers", "Content-Type,Authorization")

                    if c.Request.Method == "OPTIONS" {
                        c.AbortWithStatus(204)
                        return
                    }

                    c.Next()
                }
            }

            // 限流中间件
            func RateLimitMiddleware(limit int) gin.HandlerFunc {
                limiter := rate.NewLimiter(rate.Limit(limit), limit)

                return func(c *gin.Context) {
                    if !limiter.Allow() {
                        c.JSON(429, gin.H{"error": "请求过于频繁"})
                        c.Abort()
                        return
                    }
                    c.Next()
                }
            }

            // 应用
            api := router.Group("/api")
            api.Use(CORSMiddleware(), RateLimitMiddleware(100))

2.5 动态路由

01.参数路由
    a.单参数
        a.基础用法
            // 单个路径参数
            router.GET("/user/:id", func(c *gin.Context) {
                id := c.Param("id")

                // 转换为整数
                userID, err := strconv.Atoi(id)
                if err != nil {
                    c.JSON(400, gin.H{"error": "无效的用户ID"})
                    return
                }

                user := getUserByID(userID)
                c.JSON(200, user)
            })

            // 请求示例:
            // GET /user/123
            // 响应:{"id": 123, "name": "Alice"}
        b.参数验证
            // UUID参数验证
            router.GET("/article/:uuid", func(c *gin.Context) {
                uuid := c.Param("uuid")

                // 验证UUID格式
                matched, _ := regexp.MatchString(`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid)
                if !matched {
                    c.JSON(400, gin.H{"error": "无效的UUID格式"})
                    return
                }

                article := getArticleByUUID(uuid)
                c.JSON(200, article)
            })

            // 请求:GET /article/550e8400-e29b-41d4-a716-446655440000
    b.多参数
        a.日期路径
            // 多个路径参数
            router.GET("/posts/:year/:month/:day", func(c *gin.Context) {
                year := c.Param("year")
                month := c.Param("month")
                day := c.Param("day")

                // 验证日期格式
                date := fmt.Sprintf("%s-%s-%s", year, month, day)
                _, err := time.Parse("2006-01-02", date)
                if err != nil {
                    c.JSON(400, gin.H{"error": "无效的日期格式"})
                    return
                }

                posts := getPostsByDate(year, month, day)
                c.JSON(200, gin.H{
                    "date": date,
                    "posts": posts,
                })
            })

            // 请求:GET /posts/2024/01/15
            // 响应:{"date": "2024-01-15", "posts": [...]}
        b.嵌套资源
            // 嵌套资源路径
            router.GET("/users/:userId/posts/:postId", func(c *gin.Context) {
                userID, _ := strconv.Atoi(c.Param("userId"))
                postID, _ := strconv.Atoi(c.Param("postId"))

                // 验证用户拥有该文章
                if !userOwnsPost(userID, postID) {
                    c.JSON(403, gin.H{"error": "无权访问"})
                    return
                }

                post := getPost(postID)
                c.JSON(200, post)
            })

            // 请求:GET /users/123/posts/456
    c.通配符参数
        a.匹配所有路径
            // 通配符匹配剩余路径
            router.GET("/files/*filepath", func(c *gin.Context) {
                filepath := c.Param("filepath")

                // 安全检查,防止路径穿越
                if strings.Contains(filepath, "..") {
                    c.JSON(400, gin.H{"error": "非法路径"})
                    return
                }

                fullPath := "./static" + filepath
                c.File(fullPath)
            })

            // 请求示例:
            // GET /files/images/logo.png -> ./static/images/logo.png
            // GET /files/css/style.css   -> ./static/css/style.css
        b.SPA路由
            // 单页应用fallback
            router.NoRoute(func(c *gin.Context) {
                // 如果是API请求,返回404
                if strings.HasPrefix(c.Request.URL.Path, "/api/") {
                    c.JSON(404, gin.H{"error": "接口不存在"})
                    return
                }

                // 其他请求返回index.html
                c.File("./dist/index.html")
            })

            // Vue/React应用的路由交给前端处理
    d.参数类型转换
        a.类型安全处理
            // 参数类型转换辅助函数
            func getIntParam(c *gin.Context, key string) (int, error) {
                str := c.Param(key)
                return strconv.Atoi(str)
            }

            func getInt64Param(c *gin.Context, key string) (int64, error) {
                str := c.Param(key)
                return strconv.ParseInt(str, 10, 64)
            }

            // 使用
            router.GET("/product/:id", func(c *gin.Context) {
                id, err := getIntParam(c, "id")
                if err != nil {
                    c.JSON(400, gin.H{"error": "ID必须是数字"})
                    return
                }

                product := getProduct(id)
                c.JSON(200, product)
            })

02.正则匹配
    a.路径约束
        a.参数格式验证
            // Gin本身不直接支持正则路由,但可以通过中间件实现
            func RegexMiddleware(pattern string) gin.HandlerFunc {
                re := regexp.MustCompile(pattern)
                return func(c *gin.Context) {
                    path := c.Request.URL.Path
                    if !re.MatchString(path) {
                        c.JSON(400, gin.H{"error": "路径格式不正确"})
                        c.Abort()
                        return
                    }
                    c.Next()
                }
            }

            // 验证ID格式(只允许数字)
            router.GET("/users/:id", func(c *gin.Context) {
                id := c.Param("id")
                if matched, _ := regexp.MatchString(`^\d+$`, id); !matched {
                    c.JSON(400, gin.H{"error": "ID必须是数字"})
                    return
                }
                c.JSON(200, gin.H{"user_id": id})
            })
    d.使用场景
        a.常见格式验证
            // UUID格式验证
            router.GET("/resources/:uuid", func(c *gin.Context) {
                uuid := c.Param("uuid")
                pattern := `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`
                if matched, _ := regexp.MatchString(pattern, uuid); !matched {
                    c.JSON(400, gin.H{"error": "无效的UUID格式"})
                    return
                }
                c.JSON(200, gin.H{"uuid": uuid})
            })

            // 日期格式验证 (YYYY-MM-DD)
            router.GET("/reports/:date", func(c *gin.Context) {
                date := c.Param("date")
                pattern := `^\d{4}-\d{2}-\d{2}$`
                if matched, _ := regexp.MatchString(pattern, date); !matched {
                    c.JSON(400, gin.H{"error": "日期格式必须是YYYY-MM-DD"})
                    return
                }
                c.JSON(200, gin.H{"date": date})
            })

03.路由优先级
    a.匹配顺序
        a.优先级规则
            // Gin路由优先级:
            // 1. 静态路由(精确匹配)
            // 2. 参数路由(:param)
            // 3. 通配符路由(*param)

            router.GET("/users/new", func(c *gin.Context) {
                c.JSON(200, gin.H{"page": "new user form"})
            })

            router.GET("/users/:id", func(c *gin.Context) {
                c.JSON(200, gin.H{"user_id": c.Param("id")})
            })

            router.GET("/users/*action", func(c *gin.Context) {
                c.JSON(200, gin.H{"action": c.Param("action")})
            })

            // 请求 GET /users/new -> 匹配第一个(静态路由)
            // 请求 GET /users/123 -> 匹配第二个(参数路由)
            // 请求 GET /users/admin/delete -> 匹配第三个(通配符)
    d.调试技巧
        a.路由调试
            // 打印所有注册的路由
            func PrintRoutes(router *gin.Engine) {
                routes := router.Routes()
                for _, route := range routes {
                    fmt.Printf("%s %s -> %s\n", route.Method, route.Path, route.Handler)
                }
            }

            // 使用
            PrintRoutes(router)

04.动态注册
    a.运行时注册
        a.动态添加路由
            // 路由管理器
            type RouteManager struct {
                router *gin.Engine
                routes map[string]gin.HandlerFunc
                mu     sync.RWMutex
            }

            func NewRouteManager(router *gin.Engine) *RouteManager {
                return &RouteManager{
                    router: router,
                    routes: make(map[string]gin.HandlerFunc),
                }
            }

            // 动态添加路由
            func (rm *RouteManager) AddRoute(method, path string, handler gin.HandlerFunc) {
                rm.mu.Lock()
                defer rm.mu.Unlock()

                key := method + ":" + path
                rm.routes[key] = handler

                // 注册到Gin
                switch method {
                case "GET":
                    rm.router.GET(path, handler)
                case "POST":
                    rm.router.POST(path, handler)
                case "PUT":
                    rm.router.PUT(path, handler)
                case "DELETE":
                    rm.router.DELETE(path, handler)
                }

                log.Printf("路由已添加: %s %s", method, path)
            }

            // 使用示例
            rm := NewRouteManager(router)

            // 运行时动态添加路由
            rm.AddRoute("GET", "/dynamic/test", func(c *gin.Context) {
                c.JSON(200, gin.H{"message": "动态路由"})
            })
    b.配置驱动
        a.从配置文件加载路由
            // 路由配置结构
            type RouteConfig struct {
                Method      string   `yaml:"method"`
                Path        string   `yaml:"path"`
                Handler     string   `yaml:"handler"`
                Middlewares []string `yaml:"middlewares"`
            }

            // routes.yaml
            /*
            routes:
              - method: GET
                path: /api/users
                handler: listUsers
                middlewares:
                  - auth
                  - logger
              - method: POST
                path: /api/users
                handler: createUser
                middlewares:
                  - auth
            */

            // 加载配置并注册路由
            func LoadRoutesFromConfig(router *gin.Engine, configFile string) error {
                data, err := ioutil.ReadFile(configFile)
                if err != nil {
                    return err
                }

                var config struct {
                    Routes []RouteConfig `yaml:"routes"`
                }

                if err := yaml.Unmarshal(data, &config); err != nil {
                    return err
                }

                // 处理器映射
                handlers := map[string]gin.HandlerFunc{
                    "listUsers":   listUsersHandler,
                    "createUser":  createUserHandler,
                }

                // 中间件映射
                middlewares := map[string]gin.HandlerFunc{
                    "auth":   authMiddleware,
                    "logger": loggerMiddleware,
                }

                // 注册路由
                for _, route := range config.Routes {
                    handler := handlers[route.Handler]
                    if handler == nil {
                        continue
                    }

                    // 构建中间件链
                    var mws []gin.HandlerFunc
                    for _, mw := range route.Middlewares {
                        if m := middlewares[mw]; m != nil {
                            mws = append(mws, m)
                        }
                    }
                    mws = append(mws, handler)

                    router.Handle(route.Method, route.Path, mws...)
                }

                return nil
            }
    c.条件路由
        a.功能开关
            // 功能开关管理
            type FeatureFlags struct {
                flags map[string]bool
                mu    sync.RWMutex
            }

            func NewFeatureFlags() *FeatureFlags {
                return &FeatureFlags{
                    flags: make(map[string]bool),
                }
            }

            func (ff *FeatureFlags) IsEnabled(feature string) bool {
                ff.mu.RLock()
                defer ff.mu.RUnlock()
                return ff.flags[feature]
            }

            func (ff *FeatureFlags) Enable(feature string) {
                ff.mu.Lock()
                defer ff.mu.Unlock()
                ff.flags[feature] = true
            }

            // 条件路由中间件
            func FeatureGate(ff *FeatureFlags, feature string) gin.HandlerFunc {
                return func(c *gin.Context) {
                    if !ff.IsEnabled(feature) {
                        c.JSON(404, gin.H{"error": "功能未启用"})
                        c.Abort()
                        return
                    }
                    c.Next()
                }
            }

            // 使用
            ff := NewFeatureFlags()
            ff.Enable("new_api")

            router.GET("/api/v2/users",
                FeatureGate(ff, "new_api"),
                newAPIHandler,
            )
        b.A/B测试
            // A/B测试中间件
            func ABTestMiddleware() gin.HandlerFunc {
                return func(c *gin.Context) {
                    // 根据用户ID或随机分配版本
                    userID := c.GetHeader("User-ID")
                    hash := hashString(userID)

                    if hash%2 == 0 {
                        c.Set("ab_version", "A")
                    } else {
                        c.Set("ab_version", "B")
                    }

                    c.Next()
                }
            }

            // 根据版本执行不同逻辑
            router.GET("/api/feature", ABTestMiddleware(), func(c *gin.Context) {
                version := c.GetString("ab_version")

                if version == "A" {
                    // 版本A的逻辑
                    c.JSON(200, gin.H{"version": "A", "data": getDataV1()})
                } else {
                    // 版本B的逻辑
                    c.JSON(200, gin.H{"version": "B", "data": getDataV2()})
                }
            })
        c.灰度发布
            // 灰度发布配置
            type GrayReleaseConfig struct {
                Percentage int      // 灰度百分比
                UserIDs    []string // 白名单用户
                IPRanges   []string // IP白名单
            }

            // 灰度发布中间件
            func GrayReleaseMiddleware(config GrayReleaseConfig) gin.HandlerFunc {
                return func(c *gin.Context) {
                    userID := c.GetHeader("User-ID")
                    clientIP := c.ClientIP()

                    // 检查白名单
                    for _, id := range config.UserIDs {
                        if id == userID {
                            c.Set("use_new_version", true)
                            c.Next()
                            return
                        }
                    }

                    // 检查IP范围
                    for _, ipRange := range config.IPRanges {
                        if strings.HasPrefix(clientIP, ipRange) {
                            c.Set("use_new_version", true)
                            c.Next()
                            return
                        }
                    }

                    // 按百分比灰度
                    hash := hashString(userID + clientIP)
                    if hash%100 < config.Percentage {
                        c.Set("use_new_version", true)
                    } else {
                        c.Set("use_new_version", false)
                    }

                    c.Next()
                }
            }

            // 使用
            grayConfig := GrayReleaseConfig{
                Percentage: 10, // 10%流量
                UserIDs:    []string{"user1", "user2"},
                IPRanges:   []string{"192.168.1."},
            }

            router.GET("/api/feature", GrayReleaseMiddleware(grayConfig), func(c *gin.Context) {
                useNew := c.GetBool("use_new_version")

                if useNew {
                    c.JSON(200, newVersionHandler())
                } else {
                    c.JSON(200, oldVersionHandler())
                }
            })
    d.路由管理
        a.路由CRUD
            // 路由管理API
            type RouteInfo struct {
                ID          string    `json:"id"`
                Method      string    `json:"method"`
                Path        string    `json:"path"`
                Description string    `json:"description"`
                Enabled     bool      `json:"enabled"`
                CreatedAt   time.Time `json:"created_at"`
            }

            type RouteRegistry struct {
                routes map[string]*RouteInfo
                mu     sync.RWMutex
            }

            func NewRouteRegistry() *RouteRegistry {
                return &RouteRegistry{
                    routes: make(map[string]*RouteInfo),
                }
            }

            // 创建路由
            func (rr *RouteRegistry) CreateRoute(info *RouteInfo) error {
                rr.mu.Lock()
                defer rr.mu.Unlock()

                if _, exists := rr.routes[info.ID]; exists {
                    return errors.New("路由已存在")
                }

                info.CreatedAt = time.Now()
                info.Enabled = true
                rr.routes[info.ID] = info

                return nil
            }

            // 查询路由
            func (rr *RouteRegistry) GetRoute(id string) (*RouteInfo, error) {
                rr.mu.RLock()
                defer rr.mu.RUnlock()

                route, exists := rr.routes[id]
                if !exists {
                    return nil, errors.New("路由不存在")
                }

                return route, nil
            }

            // 更新路由
            func (rr *RouteRegistry) UpdateRoute(id string, info *RouteInfo) error {
                rr.mu.Lock()
                defer rr.mu.Unlock()

                if _, exists := rr.routes[id]; !exists {
                    return errors.New("路由不存在")
                }

                info.ID = id
                rr.routes[id] = info

                return nil
            }

            // 删除路由
            func (rr *RouteRegistry) DeleteRoute(id string) error {
                rr.mu.Lock()
                defer rr.mu.Unlock()

                delete(rr.routes, id)
                return nil
            }

            // 列出所有路由
            func (rr *RouteRegistry) ListRoutes() []*RouteInfo {
                rr.mu.RLock()
                defer rr.mu.RUnlock()

                routes := make([]*RouteInfo, 0, len(rr.routes))
                for _, route := range rr.routes {
                    routes = append(routes, route)
                }

                return routes
            }

            // 管理API
            registry := NewRouteRegistry()

            // 创建路由
            admin.POST("/routes", func(c *gin.Context) {
                var info RouteInfo
                if err := c.ShouldBindJSON(&info); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                if err := registry.CreateRoute(&info); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                c.JSON(201, info)
            })

            // 查询路由列表
            admin.GET("/routes", func(c *gin.Context) {
                routes := registry.ListRoutes()
                c.JSON(200, routes)
            })

2.6 路由中间件

01.中间件概念
    a.执行流程
        a.洋葱模型
            // 中间件执行流程(洋葱模型)
            func Middleware1() gin.HandlerFunc {
                return func(c *gin.Context) {
                    fmt.Println("M1 - 请求前")
                    c.Next()
                    fmt.Println("M1 - 响应后")
                }
            }

            func Middleware2() gin.HandlerFunc {
                return func(c *gin.Context) {
                    fmt.Println("M2 - 请求前")
                    c.Next()
                    fmt.Println("M2 - 响应后")
                }
            }

            router.GET("/test", Middleware1(), Middleware2(), func(c *gin.Context) {
                fmt.Println("Handler - 处理请求")
                c.JSON(200, gin.H{"message": "ok"})
            })

            // 输出顺序:
            // M1 - 请求前
            // M2 - 请求前
            // Handler - 处理请求
            // M2 - 响应后
            // M1 - 响应后
    c.执行顺序
        a.控制流程
            // c.Next() - 继续执行下一个中间件
            func LoggerMiddleware() gin.HandlerFunc {
                return func(c *gin.Context) {
                    start := time.Now()
                    c.Next() // 继续执行
                    latency := time.Since(start)
                    log.Printf("耗时: %v", latency)
                }
            }

            // c.Abort() - 终止后续中间件
            func AuthMiddleware() gin.HandlerFunc {
                return func(c *gin.Context) {
                    token := c.GetHeader("Authorization")
                    if token == "" {
                        c.JSON(401, gin.H{"error": "未授权"})
                        c.Abort() // 终止执行
                        return
                    }
                    c.Next()
                }
            }

02.路由级中间件
    a.单路由中间件
        a.路由级应用
            // 为特定路由添加中间件
            router.GET("/admin/dashboard",
                AuthMiddleware(),
                AdminMiddleware(),
                func(c *gin.Context) {
                    c.JSON(200, gin.H{"page": "dashboard"})
                },
            )

            // 只有这个路由会执行这些中间件
    b.多个中间件
        a.中间件链
            // 多个中间件按顺序执行
            router.POST("/api/data",
                LoggerMiddleware(),      // 1. 日志记录
                AuthMiddleware(),        // 2. 身份验证
                RateLimitMiddleware(),   // 3. 限流
                ValidateMiddleware(),    // 4. 数据验证
                func(c *gin.Context) {   // 5. 业务处理
                    c.JSON(200, gin.H{"status": "success"})
                },
            )

03.分组中间件
    a.Group.Use()
        a.分组中间件应用
            // 为整个分组添加中间件
            api := router.Group("/api")
            api.Use(CORSMiddleware(), LoggerMiddleware())
            {
                api.GET("/users", listUsers)
                api.POST("/users", createUser)
            }

            // 所有 /api/* 路由都会执行这些中间件
    b.嵌套分组
        a.中间件继承
            // 全局中间件
            router.Use(RecoveryMiddleware())

            // API分组中间件
            api := router.Group("/api")
            api.Use(CORSMiddleware())
            {
                // v1分组中间件
                v1 := api.Group("/v1")
                v1.Use(RateLimitMiddleware())
                {
                    // 认证分组中间件
                    auth := v1.Group("/auth")
                    auth.Use(AuthMiddleware())
                    {
                        auth.GET("/profile", getProfile)
                        // 执行顺序:Recovery -> CORS -> RateLimit -> Auth -> Handler
                    }
                }
            }

04.中间件最佳实践
    a.职责单一
        a.单一职责示例
            // 好的做法:每个中间件只做一件事
            func LoggerMiddleware() gin.HandlerFunc {
                return func(c *gin.Context) {
                    start := time.Now()
                    c.Next()
                    log.Printf("%s %s - %v", c.Request.Method, c.Request.URL.Path, time.Since(start))
                }
            }

            func AuthMiddleware() gin.HandlerFunc {
                return func(c *gin.Context) {
                    token := c.GetHeader("Authorization")
                    if !validateToken(token) {
                        c.AbortWithStatusJSON(401, gin.H{"error": "未授权"})
                        return
                    }
                    c.Next()
                }
            }
    b.顺序设计
        a.推荐顺序
            // 推荐的中间件顺序
            router.Use(
                RecoveryMiddleware(),    // 1. 错误恢复(最外层)
                LoggerMiddleware(),      // 2. 日志记录
                CORSMiddleware(),        // 3. CORS处理
                RateLimitMiddleware(),   // 4. 限流
                AuthMiddleware(),        // 5. 身份验证
                // 业务中间件...
            )
    c.错误处理
        a.统一错误处理
            func ErrorHandlerMiddleware() gin.HandlerFunc {
                return func(c *gin.Context) {
                    c.Next()

                    // 检查是否有错误
                    if len(c.Errors) > 0 {
                        err := c.Errors.Last()

                        // 记录错误日志
                        log.Printf("Error: %v", err)

                        // 返回友好的错误信息
                        c.JSON(500, gin.H{
                            "error": "服务器内部错误",
                            "message": err.Error(),
                        })
                    }
                }
            }

3 请求处理

3.1 请求绑定

01.JSON绑定
    a.ShouldBindJSON
        a.基础使用
            // 定义结构体
            type CreateUserRequest struct {
                Username string `json:"username" binding:"required,min=3,max=20"`
                Email    string `json:"email" binding:"required,email"`
                Age      int    `json:"age" binding:"required,gte=0,lte=120"`
                Password string `json:"password" binding:"required,min=6"`
            }

            // 使用ShouldBindJSON
            router.POST("/users", func(c *gin.Context) {
                var req CreateUserRequest

                if err := c.ShouldBindJSON(&req); err != nil {
                    c.JSON(400, gin.H{
                        "error": "参数错误",
                        "details": err.Error(),
                    })
                    return
                }

                // 业务逻辑
                user := createUser(req)
                c.JSON(201, gin.H{"user": user})
            })

            // 请求示例:
            // POST /users
            // Content-Type: application/json
            // {
            //   "username": "alice",
            //   "email": "[email protected]",
            //   "age": 25,
            //   "password": "secret123"
            // }
        b.完整示例
            // 复杂结构体绑定
            type Article struct {
                Title   string   `json:"title" binding:"required,min=5,max=200"`
                Content string   `json:"content" binding:"required,min=10"`
                Tags    []string `json:"tags" binding:"required,min=1,max=5,dive,min=2,max=20"`
                Author  Author   `json:"author" binding:"required"`
            }

            type Author struct {
                Name  string `json:"name" binding:"required"`
                Email string `json:"email" binding:"required,email"`
            }

            router.POST("/articles", func(c *gin.Context) {
                var article Article

                if err := c.ShouldBindJSON(&article); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                c.JSON(201, article)
            })

            // 请求示例:
            // {
            //   "title": "Go Web Development",
            //   "content": "This is a comprehensive guide...",
            //   "tags": ["go", "web", "tutorial"],
            //   "author": {
            //     "name": "Alice",
            //     "email": "[email protected]"
            //   }
            // }
    b.BindJSON
        a.自动响应
            // BindJSON会在绑定失败时自动返回400
            router.POST("/quick", func(c *gin.Context) {
                var req struct {
                    Name string `json:"name" binding:"required"`
                }

                // 绑定失败会自动返回400,不会执行后续代码
                if err := c.BindJSON(&req); err != nil {
                    return
                }

                c.JSON(200, gin.H{"name": req.Name})
            })
    c.验证标签
        a.常用验证规则
            type Product struct {
                // 必填
                Name string `json:"name" binding:"required"`

                // 长度限制
                Description string `json:"description" binding:"min=10,max=500"`

                // 数值范围
                Price float64 `json:"price" binding:"required,gt=0,lt=10000"`
                Stock int     `json:"stock" binding:"gte=0"`

                // 枚举值
                Status string `json:"status" binding:"oneof=draft published archived"`

                // 邮箱格式
                ContactEmail string `json:"contact_email" binding:"omitempty,email"`

                // URL格式
                Website string `json:"website" binding:"omitempty,url"`

                // 数组验证
                Images []string `json:"images" binding:"required,min=1,max=10,dive,url"`
            }

02.Form绑定
    a.表单数据
        a.基础Form绑定
            // 表单结构体
            type LoginForm struct {
                Username string `form:"username" binding:"required"`
                Password string `form:"password" binding:"required,min=6"`
                Remember bool   `form:"remember"`
            }

            // 处理表单提交
            router.POST("/login", func(c *gin.Context) {
                var form LoginForm

                if err := c.ShouldBind(&form); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                // 验证登录
                if form.Username == "admin" && form.Password == "password" {
                    c.JSON(200, gin.H{
                        "message": "登录成功",
                        "remember": form.Remember,
                    })
                } else {
                    c.JSON(401, gin.H{"error": "用户名或密码错误"})
                }
            })

            // HTML表单:
            // <form method="POST" action="/login">
            //   <input name="username" required>
            //   <input type="password" name="password" required>
            //   <input type="checkbox" name="remember">
            //   <button type="submit">登录</button>
            // </form>

            // curl测试:
            // curl -X POST http://localhost:8080/login \
            //   -d "username=admin&password=password&remember=true"
        b.文件上传Form
            // 文件上传表单
            type UploadForm struct {
                Title       string                `form:"title" binding:"required"`
                Description string                `form:"description"`
                File        *multipart.FileHeader `form:"file" binding:"required"`
            }

            router.POST("/upload", func(c *gin.Context) {
                var form UploadForm

                if err := c.ShouldBind(&form); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                // 保存文件
                filename := filepath.Base(form.File.Filename)
                if err := c.SaveUploadedFile(form.File, "./uploads/"+filename); err != nil {
                    c.JSON(500, gin.H{"error": "保存失败"})
                    return
                }

                c.JSON(200, gin.H{
                    "title": form.Title,
                    "filename": filename,
                    "size": form.File.Size,
                })
            })
    b.Query绑定
        a.查询参数绑定
            // 查询参数结构体
            type PageQuery struct {
                Page     int      `form:"page" binding:"min=1"`
                PageSize int      `form:"page_size" binding:"min=1,max=100"`
                Sort     string   `form:"sort" binding:"oneof=asc desc"`
                Keyword  string   `form:"keyword"`
                Tags     []string `form:"tags"`
            }

            router.GET("/search", func(c *gin.Context) {
                var query PageQuery
                query.Page = 1        // 默认值
                query.PageSize = 10
                query.Sort = "desc"

                if err := c.ShouldBindQuery(&query); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                // 执行搜索
                results := performSearch(query)

                c.JSON(200, gin.H{
                    "page": query.Page,
                    "page_size": query.PageSize,
                    "results": results,
                })
            })

            // 请求示例:
            // GET /search?page=2&page_size=20&sort=asc&keyword=golang&tags=web&tags=api
    c.URI绑定
        a.路径参数绑定
            // URI参数结构体
            type UserURI struct {
                ID   int    `uri:"id" binding:"required,min=1"`
                Name string `uri:"name" binding:"required,alphanum"`
            }

            router.GET("/users/:id/:name", func(c *gin.Context) {
                var uri UserURI

                if err := c.ShouldBindUri(&uri); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                c.JSON(200, gin.H{
                    "id": uri.ID,
                    "name": uri.Name,
                })
            })

            // 请求:GET /users/123/alice
            // 响应:{"id": 123, "name": "alice"}
    d.Header绑定
        a.请求头绑定
            // Header结构体
            type RequestHeaders struct {
                Authorization string `header:"Authorization" binding:"required"`
                UserAgent     string `header:"User-Agent"`
                ContentType   string `header:"Content-Type"`
                AcceptLang    string `header:"Accept-Language"`
            }

            router.GET("/headers", func(c *gin.Context) {
                var headers RequestHeaders

                if err := c.ShouldBindHeader(&headers); err != nil {
                    c.JSON(400, gin.H{"error": "缺少必需的请求头"})
                    return
                }

                c.JSON(200, gin.H{
                    "auth": headers.Authorization,
                    "user_agent": headers.UserAgent,
                    "content_type": headers.ContentType,
                })
            })

            // curl测试:
            // curl http://localhost:8080/headers \
            //   -H "Authorization: Bearer token123" \
            //   -H "User-Agent: MyApp/1.0"

03.XML绑定
    a.ShouldBindXML
        a.XML解析
            type User struct {
                XMLName xml.Name `xml:"user"`
                ID      int      `xml:"id,attr"`
                Name    string   `xml:"name"`
                Email   string   `xml:"email"`
            }

            router.POST("/xml", func(c *gin.Context) {
                var user User
                if err := c.ShouldBindXML(&user); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }
                c.JSON(200, user)
            })

            // 请求:
            // <user id="1">
            //   <name>Alice</name>
            //   <email>[email protected]</email>
            // </user>
    b.XML响应
        a.XML序列化
            router.GET("/user/xml", func(c *gin.Context) {
                user := User{
                    ID:    1,
                    Name:  "Alice",
                    Email: "[email protected]",
                }
                c.XML(200, user)
            })

            // 响应:
            // <?xml version="1.0" encoding="UTF-8"?>
            // <user id="1">
            //   <name>Alice</name>
            //   <email>[email protected]</email>
            // </user>

04.自定义绑定
    a.Binding接口
        a.自定义验证器
            import "github.com/go-playground/validator/v10"

            // 自定义验证函数
            func validatePhone(fl validator.FieldLevel) bool {
                phone := fl.Field().String()
                matched, _ := regexp.MatchString(`^1[3-9]\d{9}$`, phone)
                return matched
            }

            // 注册验证器
            if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
                v.RegisterValidation("phone", validatePhone)
            }

            // 使用
            type UserRequest struct {
                Phone string `json:"phone" binding:"required,phone"`
            }
    c.类型转换
        a.时间处理
            type Event struct {
                Name      string    `json:"name"`
                StartTime time.Time `json:"start_time" time_format:"2006-01-02 15:04:05"`
            }

            router.POST("/event", func(c *gin.Context) {
                var event Event
                if err := c.ShouldBindJSON(&event); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }
                c.JSON(200, event)
            })

3.2 参数获取

01.路径参数
    a.Param方法
        a.基础用法
            router.GET("/users/:id", func(c *gin.Context) {
                id := c.Param("id")
                c.JSON(200, gin.H{"user_id": id})
            })

            // 多个参数
            router.GET("/posts/:category/:id", func(c *gin.Context) {
                category := c.Param("category")
                id := c.Param("id")
                c.JSON(200, gin.H{
                    "category": category,
                    "id": id,
                })
            })
    b.参数验证
        a.类型转换和验证
            router.GET("/users/:id", func(c *gin.Context) {
                idStr := c.Param("id")

                // 转换为整数
                id, err := strconv.Atoi(idStr)
                if err != nil {
                    c.JSON(400, gin.H{"error": "ID必须是数字"})
                    return
                }

                // 范围验证
                if id < 1 || id > 10000 {
                    c.JSON(400, gin.H{"error": "ID超出范围"})
                    return
                }

                user := getUserByID(id)
                c.JSON(200, user)
            })

02.查询参数
    a.Query方法
        a.基础查询
            router.GET("/search", func(c *gin.Context) {
                // 获取查询参数
                keyword := c.Query("keyword")
                page := c.DefaultQuery("page", "1")
                pageSize := c.DefaultQuery("page_size", "10")

                c.JSON(200, gin.H{
                    "keyword": keyword,
                    "page": page,
                    "page_size": pageSize,
                })
            })

            // 请求:GET /search?keyword=golang&page=2&page_size=20
    c.GetQuery
        a.检查参数存在性
            router.GET("/filter", func(c *gin.Context) {
                // 检查参数是否存在
                sort, exists := c.GetQuery("sort")
                if !exists {
                    sort = "created_at"
                }

                order, exists := c.GetQuery("order")
                if !exists {
                    order = "desc"
                }

                c.JSON(200, gin.H{
                    "sort": sort,
                    "order": order,
                })
            })
    d.QueryArray
        a.多值参数
            router.GET("/filter", func(c *gin.Context) {
                // 获取数组参数
                tags := c.QueryArray("tags")
                ids := c.QueryArray("ids")

                c.JSON(200, gin.H{
                    "tags": tags,
                    "ids": ids,
                })
            })

            // 请求:GET /filter?tags=go&tags=web&ids=1&ids=2&ids=3
            // 响应:{"tags": ["go", "web"], "ids": ["1", "2", "3"]}

03.请求头
    a.GetHeader
        a.获取请求头
            router.GET("/headers", func(c *gin.Context) {
                // 获取标准头部
                contentType := c.GetHeader("Content-Type")
                auth := c.GetHeader("Authorization")
                userAgent := c.GetHeader("User-Agent")

                c.JSON(200, gin.H{
                    "content_type": contentType,
                    "auth": auth,
                    "user_agent": userAgent,
                })
            })
    d.头部处理
        a.解析Token
            router.GET("/protected", func(c *gin.Context) {
                auth := c.GetHeader("Authorization")

                // 解析Bearer Token
                if !strings.HasPrefix(auth, "Bearer ") {
                    c.JSON(401, gin.H{"error": "无效的Authorization头"})
                    return
                }

                token := strings.TrimPrefix(auth, "Bearer ")

                // 验证token
                if !validateToken(token) {
                    c.JSON(401, gin.H{"error": "无效的token"})
                    return
                }

                c.JSON(200, gin.H{"message": "认证成功"})
            })

04.请求体
    a.GetRawData
        a.获取原始数据
            router.POST("/raw", func(c *gin.Context) {
                // 获取原始请求体
                data, err := c.GetRawData()
                if err != nil {
                    c.JSON(400, gin.H{"error": "读取失败"})
                    return
                }

                // 处理原始数据
                log.Printf("收到数据: %s", string(data))

                c.JSON(200, gin.H{
                    "received": len(data),
                    "data": string(data),
                })
            })
    c.PostForm
        a.表单数据
            router.POST("/form", func(c *gin.Context) {
                // 获取表单字段
                username := c.PostForm("username")
                password := c.PostForm("password")
                remember := c.DefaultPostForm("remember", "false")

                c.JSON(200, gin.H{
                    "username": username,
                    "password": password,
                    "remember": remember,
                })
            })

            // 请求:
            // POST /form
            // Content-Type: application/x-www-form-urlencoded
            // username=alice&password=secret&remember=true

3.3 文件上传

01.单文件上传
    a.FormFile
        a.基础上传
            router.POST("/upload", func(c *gin.Context) {
                file, err := c.FormFile("file")
                if err != nil {
                    c.JSON(400, gin.H{"error": "文件上传失败"})
                    return
                }

                // 文件大小限制(10MB)
                if file.Size > 10*1024*1024 {
                    c.JSON(400, gin.H{"error": "文件大小超过10MB"})
                    return
                }

                // 文件类型验证
                allowedTypes := map[string]bool{
                    "image/jpeg": true,
                    "image/png":  true,
                    "image/gif":  true,
                }

                contentType := file.Header.Get("Content-Type")
                if !allowedTypes[contentType] {
                    c.JSON(400, gin.H{"error": "不支持的文件类型"})
                    return
                }

                // 生成安全的文件名
                ext := filepath.Ext(file.Filename)
                filename := fmt.Sprintf("%d%s", time.Now().Unix(), ext)
                dst := filepath.Join("./uploads", filename)

                // 保存文件
                if err := c.SaveUploadedFile(file, dst); err != nil {
                    c.JSON(500, gin.H{"error": "保存失败"})
                    return
                }

                c.JSON(200, gin.H{
                    "filename": filename,
                    "size":     file.Size,
                    "url":      "/uploads/" + filename,
                })
            })

02.多文件上传
    a.MultipartForm
        a.批量上传
            router.POST("/upload/multiple", func(c *gin.Context) {
                form, err := c.MultipartForm()
                if err != nil {
                    c.JSON(400, gin.H{"error": "获取表单失败"})
                    return
                }

                files := form.File["files"]
                var uploaded []string

                for _, file := range files {
                    // 验证文件
                    if file.Size > 10*1024*1024 {
                        continue
                    }

                    // 保存文件
                    filename := fmt.Sprintf("%d_%s", time.Now().UnixNano(), file.Filename)
                    dst := filepath.Join("./uploads", filename)

                    if err := c.SaveUploadedFile(file, dst); err != nil {
                        continue
                    }

                    uploaded = append(uploaded, filename)
                }

                c.JSON(200, gin.H{
                    "count": len(uploaded),
                    "files": uploaded,
                })
            })

03.文件处理
    a.文件类型
        a.MIME和扩展名验证
            func validateFileType(file *multipart.FileHeader) error {
                // 允许的MIME类型
                allowedMIME := map[string]bool{
                    "image/jpeg": true,
                    "image/png":  true,
                    "image/gif":  true,
                    "application/pdf": true,
                }

                // 检查MIME类型
                contentType := file.Header.Get("Content-Type")
                if !allowedMIME[contentType] {
                    return errors.New("不支持的文件类型")
                }

                // 检查扩展名
                ext := strings.ToLower(filepath.Ext(file.Filename))
                allowedExt := map[string]bool{
                    ".jpg": true, ".jpeg": true, ".png": true,
                    ".gif": true, ".pdf": true,
                }

                if !allowedExt[ext] {
                    return errors.New("不支持的文件扩展名")
                }

                return nil
            }

            router.POST("/upload", func(c *gin.Context) {
                file, _ := c.FormFile("file")

                if err := validateFileType(file); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                // 保存文件...
            })
    b.文件大小
        a.大小限制
            // 设置最大内存
            router.MaxMultipartMemory = 8 << 20 // 8 MiB

            router.POST("/upload", func(c *gin.Context) {
                file, _ := c.FormFile("file")

                // 单文件大小限制(10MB)
                maxSize := int64(10 * 1024 * 1024)
                if file.Size > maxSize {
                    c.JSON(400, gin.H{
                        "error": "文件大小超过限制",
                        "max_size": "10MB",
                        "file_size": file.Size,
                    })
                    return
                }

                c.SaveUploadedFile(file, "./uploads/"+file.Filename)
                c.JSON(200, gin.H{"message": "上传成功"})
            })
    c.文件存储
        a.本地存储
            router.POST("/upload", func(c *gin.Context) {
                file, _ := c.FormFile("file")

                // 按日期组织目录
                today := time.Now().Format("2006-01-02")
                uploadDir := filepath.Join("./uploads", today)

                // 创建目录
                if err := os.MkdirAll(uploadDir, 0755); err != nil {
                    c.JSON(500, gin.H{"error": "创建目录失败"})
                    return
                }

                // 生成唯一文件名
                ext := filepath.Ext(file.Filename)
                filename := fmt.Sprintf("%d%s", time.Now().UnixNano(), ext)
                dst := filepath.Join(uploadDir, filename)

                c.SaveUploadedFile(file, dst)
                c.JSON(200, gin.H{
                    "path": dst,
                    "url": fmt.Sprintf("/uploads/%s/%s", today, filename),
                })
            })
    d.文件命名
        a.安全文件名生成
            import "github.com/google/uuid"

            func generateSafeFilename(originalName string) string {
                ext := filepath.Ext(originalName)

                // 方式1:UUID
                uuidName := uuid.New().String() + ext

                // 方式2:时间戳
                timestamp := time.Now().UnixNano()
                timestampName := fmt.Sprintf("%d%s", timestamp, ext)

                // 方式3:哈希值
                hash := md5.Sum([]byte(originalName + time.Now().String()))
                hashName := fmt.Sprintf("%x%s", hash, ext)

                return uuidName // 推荐使用UUID
            }

            router.POST("/upload", func(c *gin.Context) {
                file, _ := c.FormFile("file")

                filename := generateSafeFilename(file.Filename)
                dst := filepath.Join("./uploads", filename)

                c.SaveUploadedFile(file, dst)
                c.JSON(200, gin.H{"filename": filename})
            })

04.安全考虑
    a.路径遍历
        a.路径验证
            func validatePath(filename string) error {
                // 禁止路径遍历
                if strings.Contains(filename, "..") {
                    return errors.New("非法的文件路径")
                }

                // 禁止绝对路径
                if filepath.IsAbs(filename) {
                    return errors.New("不允许绝对路径")
                }

                // 清理路径
                clean := filepath.Clean(filename)
                if clean != filename {
                    return errors.New("路径包含非法字符")
                }

                return nil
            }

            router.POST("/upload", func(c *gin.Context) {
                file, _ := c.FormFile("file")

                if err := validatePath(file.Filename); err != nil {
                    c.JSON(400, gin.H{"error": err.Error()})
                    return
                }

                // 使用白名单目录
                safeDir := "./uploads"
                filename := filepath.Base(file.Filename)
                dst := filepath.Join(safeDir, filename)

                // 确保目标路径在白名单目录内
                absPath, _ := filepath.Abs(dst)
                absDir, _ := filepath.Abs(safeDir)
                if !strings.HasPrefix(absPath, absDir) {
                    c.JSON(400, gin.H{"error": "非法的目标路径"})
                    return
                }

                c.SaveUploadedFile(file, dst)
            })
    b.文件类型
        a.MIME验证和内容检查
            import "net/http"

            func detectFileType(file multipart.File) (string, error) {
                // 读取文件头(前512字节)
                buffer := make([]byte, 512)
                _, err := file.Read(buffer)
                if err != nil {
                    return "", err
                }

                // 重置文件指针
                file.Seek(0, 0)

                // 检测MIME类型
                contentType := http.DetectContentType(buffer)
                return contentType, nil
            }

            router.POST("/upload", func(c *gin.Context) {
                fileHeader, _ := c.FormFile("file")
                file, _ := fileHeader.Open()
                defer file.Close()

                // 检测实际文件类型
                actualType, _ := detectFileType(file)
                declaredType := fileHeader.Header.Get("Content-Type")

                // 验证类型一致性
                if actualType != declaredType {
                    c.JSON(400, gin.H{
                        "error": "文件类型不匹配",
                        "declared": declaredType,
                        "actual": actualType,
                    })
                    return
                }

                // 白名单验证
                allowedTypes := []string{
                    "image/jpeg", "image/png", "image/gif",
                }

                allowed := false
                for _, t := range allowedTypes {
                    if actualType == t {
                        allowed = true
                        break
                    }
                }

                if !allowed {
                    c.JSON(400, gin.H{"error": "不允许的文件类型"})
                    return
                }

                c.JSON(200, gin.H{"message": "验证通过"})
            })
    c.大小限制
        a.完整的大小控制
            const (
                MaxFileSize  = 10 * 1024 * 1024  // 10MB
                MaxTotalSize = 50 * 1024 * 1024  // 50MB
                MaxFiles     = 10
            )

            router.POST("/upload/batch", func(c *gin.Context) {
                form, _ := c.MultipartForm()
                files := form.File["files"]

                // 检查文件数量
                if len(files) > MaxFiles {
                    c.JSON(400, gin.H{
                        "error": "文件数量超过限制",
                        "max": MaxFiles,
                    })
                    return
                }

                // 检查总大小
                var totalSize int64
                for _, file := range files {
                    // 单文件大小
                    if file.Size > MaxFileSize {
                        c.JSON(400, gin.H{
                            "error": "单个文件超过限制",
                            "file": file.Filename,
                            "max": "10MB",
                        })
                        return
                    }

                    totalSize += file.Size
                }

                if totalSize > MaxTotalSize {
                    c.JSON(400, gin.H{
                        "error": "总大小超过限制",
                        "max": "50MB",
                    })
                    return
                }

                // 保存文件...
                c.JSON(200, gin.H{"message": "上传成功"})
            })
    d.权限控制
        a.上传权限和审计
            // 权限检查中间件
            func UploadPermissionMiddleware() gin.HandlerFunc {
                return func(c *gin.Context) {
                    userID := c.GetInt("user_id")

                    // 检查上传权限
                    if !hasUploadPermission(userID) {
                        c.JSON(403, gin.H{"error": "无上传权限"})
                        c.Abort()
                        return
                    }

                    // 检查存储配额
                    used := getUserStorageUsed(userID)
                    quota := getUserStorageQuota(userID)

                    if used >= quota {
                        c.JSON(403, gin.H{
                            "error": "存储配额已满",
                            "used": used,
                            "quota": quota,
                        })
                        c.Abort()
                        return
                    }

                    c.Next()
                }
            }

            // 审计日志
            func logUpload(userID int, filename string, size int64) {
                log.Printf("[UPLOAD] User:%d File:%s Size:%d Time:%s",
                    userID, filename, size, time.Now().Format(time.RFC3339))

                // 写入数据库
                db.Create(&UploadLog{
                    UserID:    userID,
                    Filename:  filename,
                    Size:      size,
                    IP:        c.ClientIP(),
                    CreatedAt: time.Now(),
                })
            }

            router.POST("/upload",
                AuthMiddleware(),
                UploadPermissionMiddleware(),
                func(c *gin.Context) {
                    file, _ := c.FormFile("file")
                    userID := c.GetInt("user_id")

                    // 保存文件
                    dst := "./uploads/" + file.Filename
                    c.SaveUploadedFile(file, dst)

                    // 记录审计日志
                    logUpload(userID, file.Filename, file.Size)

                    c.JSON(200, gin.H{"message": "上传成功"})
                },
            )

4 响应处理

4.1 JSON响应

01.基础响应
    a.简单JSON
        // 使用gin.H快速创建JSON
        router.GET("/api/hello", func(c *gin.Context) {
            c.JSON(200, gin.H{
                "message": "success",
                "code": 0,
                "data": gin.H{
                    "user": "Alice",
                    "role": "admin",
                },
            })
        })

        // 响应:
        // {
        //   "message": "success",
        //   "code": 0,
        //   "data": {
        //     "user": "Alice",
        //     "role": "admin"
        //   }
        // }
    b.统一响应格式
        // 定义统一响应结构
        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(200, Response{
                Code:    0,
                Message: "success",
                Data:    data,
            })
        }

        // 错误响应
        func Error(c *gin.Context, code int, message string) {
            c.JSON(code, Response{
                Code:    -1,
                Message: message,
            })
        }

        // 使用
        router.GET("/users", func(c *gin.Context) {
            users := getUsers()
            Success(c, users)
        })

02.结构体响应
    a.结构体序列化
        // 定义结构体
        type User struct {
            ID        int       `json:"id"`
            Username  string    `json:"username"`
            Email     string    `json:"email"`
            Password  string    `json:"-"`  // 不序列化
            CreatedAt time.Time `json:"created_at"`
            UpdatedAt time.Time `json:"updated_at,omitempty"`  // 空值不输出
        }

        router.GET("/user/:id", func(c *gin.Context) {
            user := User{
                ID:       123,
                Username: "alice",
                Email:    "[email protected]",
                Password: "secret",  // 不会出现在响应中
                CreatedAt: time.Now(),
            }

            c.JSON(200, user)
        })

        // 响应:
        // {
        //   "id": 123,
        //   "username": "alice",
        //   "email": "[email protected]",
        //   "created_at": "2024-01-15T10:30:00Z"
        // }

03.IndentedJSON
    a.格式化输出
        // 开发环境使用IndentedJSON便于调试
        router.GET("/debug/user", func(c *gin.Context) {
            user := map[string]interface{}{
                "id": 123,
                "profile": map[string]interface{}{
                    "name": "Alice",
                    "tags": []string{"admin", "developer"},
                },
            }

            c.IndentedJSON(200, user)
        })

        // 响应(格式化):
        // {
        //   "id": 123,
        //   "profile": {
        //     "name": "Alice",
        //     "tags": [
        //       "admin",
        //       "developer"
        //     ]
        //   }
        // }

04.SecureJSON
    a.防止JSON劫持
        // SecureJSON在响应前添加前缀,防止JSON劫持
        router.GET("/api/secure", func(c *gin.Context) {
            data := []string{"sensitive", "data"}
            c.SecureJSON(200, data)
        })

        // 响应:while(1);["sensitive","data"]

        // JSONP支持
        router.GET("/api/jsonp", func(c *gin.Context) {
            data := gin.H{"message": "JSONP response"}
            c.JSONP(200, data)
        })

        // 请求:GET /api/jsonp?callback=handleResponse
        // 响应:handleResponse({"message":"JSONP response"})

4.2 HTML模板

01.模板加载
    a.基础加载
        // 加载所有模板
        router.LoadHTMLGlob("templates/*")

        // 加载嵌套目录
        router.LoadHTMLGlob("templates/**/*")

        // 使用示例
        router.GET("/", func(c *gin.Context) {
            c.HTML(200, "index.html", gin.H{
                "title": "首页",
            })
        })

02.渲染模板
    a.数据传递
        router.GET("/user/:id", func(c *gin.Context) {
            user := User{
                ID:   1,
                Name: "Alice",
                Email: "[email protected]",
            }

            c.HTML(200, "user.html", gin.H{
                "title": "用户详情",
                "user": user,
            })
        })

        // templates/user.html
        // <h1>{{.title}}</h1>
        // <p>姓名:{{.user.Name}}</p>
        // <p>邮箱:{{.user.Email}}</p>

03.模板语法
    a.常用语法
        // templates/list.html
        <h1>{{.title}}</h1>

        {{if .users}}
        <ul>
        {{range .users}}
            <li>{{.Name}} - {{.Email}}</li>
        {{end}}
        </ul>
        {{else}}
        <p>暂无数据</p>
        {{end}}

        // 使用
        router.GET("/users", func(c *gin.Context) {
            users := []User{
                {Name: "Alice", Email: "[email protected]"},
                {Name: "Bob", Email: "[email protected]"},
            }

            c.HTML(200, "list.html", gin.H{
                "title": "用户列表",
                "users": users,
            })
        })

04.静态文件
    a.静态资源服务
        // 静态文件目录
        router.Static("/static", "./static")
        router.StaticFS("/assets", http.Dir("./assets"))
        router.StaticFile("/favicon.ico", "./static/favicon.ico")

        // 在模板中使用
        // <link rel="stylesheet" href="/static/css/style.css">
        // <script src="/static/js/app.js"></script>

4.3 文件响应

01.文件下载
    a.基础文件下载
        router.GET("/download/:filename", func(c *gin.Context) {
            filename := c.Param("filename")
            filepath := "./files/" + filename

            // 检查文件是否存在
            if _, err := os.Stat(filepath); os.IsNotExist(err) {
                c.JSON(404, gin.H{"error": "文件不存在"})
                return
            }

            c.File(filepath)
        })

02.文件流
    a.强制下载
        router.GET("/download/attachment/:filename", func(c *gin.Context) {
            filename := c.Param("filename")
            filepath := "./files/" + filename

            // 强制下载,自定义文件名
            c.FileAttachment(filepath, "custom_"+filename)
        })

        // 设置Content-Disposition
        router.GET("/download/inline/:filename", func(c *gin.Context) {
            filename := c.Param("filename")
            filepath := "./files/" + filename

            c.Header("Content-Disposition", "inline; filename=\""+filename+"\"")
            c.File(filepath)
        })

03.FileFromFS
    a.嵌入文件系统
        import "embed"

        //go:embed static/*
        var staticFS embed.FS

        router.GET("/embed/:file", func(c *gin.Context) {
            filename := c.Param("file")
            c.FileFromFS("static/"+filename, http.FS(staticFS))
        })

04.Data响应
    a.二进制数据
        router.GET("/image", func(c *gin.Context) {
            // 读取文件
            data, err := ioutil.ReadFile("./images/logo.png")
            if err != nil {
                c.JSON(500, gin.H{"error": "读取失败"})
                return
            }

            c.Data(200, "image/png", data)
        })

        // 动态生成数据
        router.GET("/generate", func(c *gin.Context) {
            data := []byte("Hello, World!")
            c.Data(200, "text/plain", data)
        })

4.4 流式响应

01.SSE
    a.Server-Sent Events
        router.GET("/events", func(c *gin.Context) {
            c.Header("Content-Type", "text/event-stream")
            c.Header("Cache-Control", "no-cache")
            c.Header("Connection", "keep-alive")

            c.Stream(func(w io.Writer) bool {
                // 发送事件
                fmt.Fprintf(w, "data: %s\n\n", time.Now().Format(time.RFC3339))
                c.Writer.Flush()

                time.Sleep(1 * time.Second)
                return true // 返回false停止流
            })
        })

02.分块传输
    a.Chunked编码
        router.GET("/stream", func(c *gin.Context) {
            c.Header("Transfer-Encoding", "chunked")
            c.Header("Content-Type", "text/plain")

            for i := 0; i < 10; i++ {
                c.Writer.Write([]byte(fmt.Sprintf("Chunk %d\n", i)))
                c.Writer.Flush()
                time.Sleep(500 * time.Millisecond)
            }
        })

03.WebSocket升级
    a.WebSocket连接
        import "github.com/gorilla/websocket"

        var upgrader = websocket.Upgrader{
            CheckOrigin: func(r *http.Request) bool {
                return true
            },
        }

        router.GET("/ws", func(c *gin.Context) {
            conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
            if err != nil {
                return
            }
            defer conn.Close()

            for {
                _, message, err := conn.ReadMessage()
                if err != nil {
                    break
                }

                // 回显消息
                conn.WriteMessage(websocket.TextMessage, message)
            }
        })

04.性能优化
    a.缓冲控制
        router.GET("/large-data", func(c *gin.Context) {
            c.Header("Content-Type", "application/json")
            c.Writer.WriteHeader(200)

            // 使用缓冲写入
            buf := bufio.NewWriter(c.Writer)

            buf.WriteString("[")
            for i := 0; i < 10000; i++ {
                if i > 0 {
                    buf.WriteString(",")
                }
                fmt.Fprintf(buf, `{"id":%d}`, i)

                if i%100 == 0 {
                    buf.Flush() // 定期刷新
                }
            }
            buf.WriteString("]")
            buf.Flush()
        })

4.5 重定向

01.HTTP重定向
    a.基础重定向
        // 临时重定向(302)
        router.GET("/old", func(c *gin.Context) {
            c.Redirect(302, "/new")
        })

        // 永久重定向(301)
        router.GET("/old-page", func(c *gin.Context) {
            c.Redirect(301, "/new-page")
        })

        // 外部重定向
        router.GET("/external", func(c *gin.Context) {
            c.Redirect(302, "https://example.com")
        })

02.路由重定向
    a.内部重定向
        router.GET("/internal", func(c *gin.Context) {
            // 修改请求路径
            c.Request.URL.Path = "/target"
            router.HandleContext(c)
        })

        router.GET("/target", func(c *gin.Context) {
            c.JSON(200, gin.H{"message": "目标路由"})
        })

03.重定向场景
    a.登录跳转
        router.GET("/protected", func(c *gin.Context) {
            // 检查登录状态
            if !isLoggedIn(c) {
                c.Redirect(302, "/login?redirect="+c.Request.URL.Path)
                return
            }

            c.HTML(200, "protected.html", nil)
        })

        router.POST("/login", func(c *gin.Context) {
            // 登录处理...

            // 重定向到原页面
            redirect := c.DefaultQuery("redirect", "/")
            c.Redirect(302, redirect)
        })

04.最佳实践
    a.安全重定向
        func SafeRedirect(c *gin.Context, url string) {
            // 白名单检查
            allowedDomains := []string{
                "example.com",
                "app.example.com",
            }

            parsedURL, err := url.Parse(url)
            if err != nil {
                c.Redirect(302, "/")
                return
            }

            // 检查域名
            for _, domain := range allowedDomains {
                if parsedURL.Host == domain {
                    c.Redirect(302, url)
                    return
                }
            }

            c.Redirect(302, "/")
        }

4.6 响应格式化

01.统一响应
    a.标准响应结构
        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(200, Response{
                Code:    0,
                Message: "success",
                Data:    data,
            })
        }

        func Error(c *gin.Context, code int, message string) {
            c.JSON(200, Response{
                Code:    code,
                Message: message,
            })
        }

        // 使用
        router.GET("/users", func(c *gin.Context) {
            users := getUserList()
            Success(c, users)
        })

02.分页响应
    a.分页结构
        type PageResponse struct {
            Code    int         `json:"code"`
            Message string      `json:"message"`
            Data    interface{} `json:"data"`
            Page    PageInfo    `json:"page"`
        }

        type PageInfo struct {
            Total    int64 `json:"total"`
            Page     int   `json:"page"`
            PageSize int   `json:"page_size"`
            Pages    int   `json:"pages"`
        }

        router.GET("/users", func(c *gin.Context) {
            page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
            pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))

            users, total := getUsersWithPage(page, pageSize)
            pages := int(math.Ceil(float64(total) / float64(pageSize)))

            c.JSON(200, PageResponse{
                Code:    0,
                Message: "success",
                Data:    users,
                Page: PageInfo{
                    Total:    total,
                    Page:     page,
                    PageSize: pageSize,
                    Pages:    pages,
                },
            })
        })

03.错误响应
    a.错误处理
        type ErrorResponse struct {
            Code    int    `json:"code"`
            Message string `json:"message"`
            Error   string `json:"error,omitempty"`
            Stack   string `json:"stack,omitempty"`
        }

        func HandleError(c *gin.Context, err error) {
            resp := ErrorResponse{
                Code:    500,
                Message: "服务器错误",
            }

            // 开发模式显示详细错误
            if gin.Mode() == gin.DebugMode {
                resp.Error = err.Error()
                resp.Stack = string(debug.Stack())
            }

            c.JSON(500, resp)
        }

04.自定义格式
    a.自定义Render
        import "gopkg.in/yaml.v2"

        type YAMLRender struct {
            Data interface{}
        }

        func (r YAMLRender) Render(w http.ResponseWriter) error {
            w.Header().Set("Content-Type", "application/x-yaml")
            return yaml.NewEncoder(w).Encode(r.Data)
        }

        func (r YAMLRender) WriteContentType(w http.ResponseWriter) {
            w.Header().Set("Content-Type", "application/x-yaml; charset=utf-8")
        }

        // 使用
        router.GET("/yaml", func(c *gin.Context) {
            data := gin.H{"message": "YAML response"}
            c.Render(200, YAMLRender{Data: data})
        })

5 中间件

5.1 中间件概念

01.执行模型
    a.洋葱模型
        // 中间件执行流程演示
        func Middleware1() gin.HandlerFunc {
            return func(c *gin.Context) {
                fmt.Println("M1 - 请求前")
                c.Next() // 调用下一个中间件
                fmt.Println("M1 - 响应后")
            }
        }

        func Middleware2() gin.HandlerFunc {
            return func(c *gin.Context) {
                fmt.Println("M2 - 请求前")
                c.Next()
                fmt.Println("M2 - 响应后")
            }
        }

        router.GET("/test", Middleware1(), Middleware2(), func(c *gin.Context) {
            fmt.Println("Handler - 处理请求")
            c.JSON(200, gin.H{"message": "ok"})
        })

        // 执行顺序:
        // M1 - 请求前
        // M2 - 请求前
        // Handler - 处理请求
        // M2 - 响应后
        // M1 - 响应后

02.中间件类型
    a.不同级别的中间件
        // 全局中间件
        router.Use(LoggerMiddleware())
        router.Use(RecoveryMiddleware())

        // 分组中间件
        api := router.Group("/api")
        api.Use(AuthMiddleware())
        {
            api.GET("/users", listUsers)
        }

        // 路由中间件
        router.GET("/admin", AdminMiddleware(), adminHandler)

        // 条件中间件
        router.GET("/data", func(c *gin.Context) {
            if needAuth(c) {
                AuthMiddleware()(c)
            }
            c.Next()
        }, dataHandler)

03.执行顺序
    a.流程控制
        // c.Next() - 继续执行
        func LoggerMiddleware() gin.HandlerFunc {
            return func(c *gin.Context) {
                start := time.Now()
                c.Next() // 继续执行后续中间件和处理器
                latency := time.Since(start)
                log.Printf("耗时: %v", latency)
            }
        }

        // c.Abort() - 终止执行
        func AuthMiddleware() gin.HandlerFunc {
            return func(c *gin.Context) {
                token := c.GetHeader("Authorization")
                if token == "" {
                    c.JSON(401, gin.H{"error": "未授权"})
                    c.Abort() // 终止后续执行
                    return
                }
                c.Next()
            }
        }

        // c.AbortWithStatus() - 终止并设置状态码
        func RateLimitMiddleware() gin.HandlerFunc {
            return func(c *gin.Context) {
                if !checkRateLimit(c.ClientIP()) {
                    c.AbortWithStatusJSON(429, gin.H{"error": "请求过于频繁"})
                    return
                }
                c.Next()
            }
        }

04.上下文传递
    a.数据共享
        // 设置和获取上下文数据
        func AuthMiddleware() gin.HandlerFunc {
            return func(c *gin.Context) {
                token := c.GetHeader("Authorization")
                userID := validateToken(token)

                // 保存到上下文
                c.Set("user_id", userID)
                c.Set("user_role", "admin")

                c.Next()
            }
        }

        // 在处理器中获取
        router.GET("/profile", AuthMiddleware(), func(c *gin.Context) {
            // 获取上下文数据
            userID, exists := c.Get("user_id")
            if !exists {
                c.JSON(500, gin.H{"error": "用户信息丢失"})
                return
            }

            // 类型断言
            id := userID.(int)

            // 或使用类型安全的方法
            role := c.GetString("user_role")

            c.JSON(200, gin.H{
                "user_id": id,
                "role": role,
            })
        })

5.2 内置中间件

01.Logger
    a.基础日志
        // 使用默认Logger
        router.Use(gin.Logger())

        // 自定义日志格式
        router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
            return fmt.Sprintf("[%s] %s %s %d %s %s\n",
                param.TimeStamp.Format("2006-01-02 15:04:05"),
                param.Method,
                param.Path,
                param.StatusCode,
                param.Latency,
                param.ClientIP,
            )
        }))

        // 输出到文件
        f, _ := os.Create("gin.log")
        gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
        router.Use(gin.Logger())

02.Recovery
    a.Panic恢复
        // 使用默认Recovery
        router.Use(gin.Recovery())

        // 自定义Recovery
        router.Use(gin.CustomRecovery(func(c *gin.Context, recovered interface{}) {
            if err, ok := recovered.(string); ok {
                c.JSON(500, gin.H{
                    "error": "服务器错误",
                    "message": err,
                })
            }
            c.AbortWithStatus(500)
        }))

        // 测试panic
        router.GET("/panic", func(c *gin.Context) {
            panic("测试panic")
        })

03.BasicAuth
    a.HTTP基础认证
        // 定义授权用户
        authorized := gin.Accounts{
            "admin": "secret",
            "user":  "password",
        }

        // 使用BasicAuth
        admin := router.Group("/admin")
        admin.Use(gin.BasicAuth(authorized))
        {
            admin.GET("/dashboard", func(c *gin.Context) {
                user := c.MustGet(gin.AuthUserKey).(string)
                c.JSON(200, gin.H{
                    "user": user,
                    "message": "欢迎访问管理后台",
                })
            })
        }

        // 请求示例:
        // curl -u admin:secret http://localhost:8080/admin/dashboard

04.CORS
    a.跨域配置
        import "github.com/gin-contrib/cors"

        // 默认CORS配置
        router.Use(cors.Default())

        // 自定义CORS配置
        router.Use(cors.New(cors.Config{
            AllowOrigins:     []string{"http://localhost:3000"},
            AllowMethods:     []string{"GET", "POST", "PUT", "DELETE"},
            AllowHeaders:     []string{"Origin", "Content-Type", "Authorization"},
            ExposeHeaders:    []string{"Content-Length"},
            AllowCredentials: true,
            MaxAge:           12 * time.Hour,
        }))

        // 允许所有来源(开发环境)
        router.Use(cors.New(cors.Config{
            AllowAllOrigins: true,
            AllowMethods:    []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
            AllowHeaders:    []string{"*"},
        }))

5.3 自定义中间件

01.中间件结构
    a.基础结构
        // 简单中间件
        func SimpleMiddleware() gin.HandlerFunc {
            return func(c *gin.Context) {
                // 请求前处理
                log.Println("请求开始")

                c.Next()

                // 请求后处理
                log.Println("请求结束")
            }
        }

        // 使用
        router.Use(SimpleMiddleware())
    b.带参数的中间件
        // 参数化中间件工厂
        func TimeoutMiddleware(timeout time.Duration) gin.HandlerFunc {
            return func(c *gin.Context) {
                ctx, cancel := context.WithTimeout(c.Request.Context(), timeout)
                defer cancel()

                c.Request = c.Request.WithContext(ctx)

                finished := make(chan struct{})
                go func() {
                    c.Next()
                    finished <- struct{}{}
                }()

                select {
                case <-finished:
                    return
                case <-ctx.Done():
                    c.JSON(408, gin.H{"error": "请求超时"})
                    c.Abort()
                }
            }
        }

        // 使用:设置30秒超时
        router.Use(TimeoutMiddleware(30 * time.Second))

02.请求前处理
    a.JWT认证中间件
        func JWTAuthMiddleware() gin.HandlerFunc {
            return func(c *gin.Context) {
                // 获取Token
                authHeader := c.GetHeader("Authorization")
                if authHeader == "" {
                    c.JSON(401, gin.H{"error": "未提供认证信息"})
                    c.Abort()
                    return
                }

                // 验证Bearer格式
                parts := strings.SplitN(authHeader, " ", 2)
                if len(parts) != 2 || parts[0] != "Bearer" {
                    c.JSON(401, gin.H{"error": "认证格式错误"})
                    c.Abort()
                    return
                }

                // 解析Token
                token := parts
                claims, err := parseJWT(token)
                if err != nil {
                    c.JSON(401, gin.H{"error": "Token无效"})
                    c.Abort()
                    return
                }

                // 存储用户信息
                c.Set("user_id", claims.UserID)
                c.Set("username", claims.Username)

                c.Next()
            }
        }

        // 使用
        router.GET("/profile", JWTAuthMiddleware(), func(c *gin.Context) {
            userID := c.GetInt("user_id")
            username := c.GetString("username")
            c.JSON(200, gin.H{
                "user_id": userID,
                "username": username,
            })
        })
    b.限流中间件
        import "golang.org/x/time/rate"

        func RateLimitMiddleware(r rate.Limit, b int) gin.HandlerFunc {
            limiters := make(map[string]*rate.Limiter)
            var mu sync.Mutex

            return func(c *gin.Context) {
                ip := c.ClientIP()

                mu.Lock()
                limiter, exists := limiters[ip]
                if !exists {
                    limiter = rate.NewLimiter(r, b)
                    limiters[ip] = limiter
                }
                mu.Unlock()

                if !limiter.Allow() {
                    c.JSON(429, gin.H{
                        "error": "请求过于频繁",
                        "retry_after": "60s",
                    })
                    c.Abort()
                    return
                }

                c.Next()
            }
        }

        // 使用:每秒10个请求,突发20个
        router.Use(RateLimitMiddleware(10, 20))

03.响应后处理
    a.性能统计中间件
        func PerformanceMiddleware() gin.HandlerFunc {
            return func(c *gin.Context) {
                start := time.Now()
                path := c.Request.URL.Path
                method := c.Request.Method

                c.Next()

                latency := time.Since(start)
                statusCode := c.Writer.Status()

                log.Printf("[%s] %s %s %d %v",
                    method,
                    path,
                    c.ClientIP(),
                    statusCode,
                    latency,
                )

                // 记录慢请求
                if latency > 1*time.Second {
                    log.Printf("慢请求警告: %s %s 耗时 %v", method, path, latency)
                }
            }
        }
    b.响应修改中间件
        func ResponseWrapperMiddleware() gin.HandlerFunc {
            return func(c *gin.Context) {
                // 创建自定义ResponseWriter
                blw := &bodyLogWriter{
                    ResponseWriter: c.Writer,
                    body:          bytes.NewBufferString(""),
                }
                c.Writer = blw

                c.Next()

                // 修改响应
                statusCode := c.Writer.Status()
                if statusCode == 200 {
                    // 包装成统一格式
                    wrapped := gin.H{
                        "code": 0,
                        "message": "success",
                        "data": json.RawMessage(blw.body.Bytes()),
                    }
                    c.JSON(200, wrapped)
                }
            }
        }

        type bodyLogWriter struct {
            gin.ResponseWriter
            body *bytes.Buffer
        }

        func (w bodyLogWriter) Write(b []byte) (int, error) {
            w.body.Write(b)
            return w.ResponseWriter.Write(b)
        }

04.错误处理
    a.Panic恢复中间件
        func RecoveryMiddleware() gin.HandlerFunc {
            return func(c *gin.Context) {
                defer func() {
                    if err := recover(); err != nil {
                        // 获取堆栈信息
                        stack := make([]byte, 4096)
                        length := runtime.Stack(stack, false)

                        log.Printf("Panic recovered: %v\n%s", err, stack[:length])

                        // 返回500错误
                        c.JSON(500, gin.H{
                            "error": "服务器内部错误",
                            "request_id": c.GetString("request_id"),
                        })

                        c.Abort()
                    }
                }()

                c.Next()
            }
        }

5.4 中间件链

01.链式执行
    a.执行顺序
        // 中间件按注册顺序执行
        router.Use(Middleware1())  // 第一个
        router.Use(Middleware2())  // 第二个
        router.Use(Middleware3())  // 第三个

        router.GET("/test", func(c *gin.Context) {
            c.JSON(200, gin.H{"message": "ok"})
        })

        // 执行流程:
        // M1请求前 -> M2请求前 -> M3请求前 -> Handler -> M3响应后 -> M2响应后 -> M1响应后

02.中间件组合
    a.功能组合
        // 组合多个中间件
        api := router.Group("/api")
        api.Use(
            CORSMiddleware(),      // 跨域
            LoggerMiddleware(),    // 日志
            AuthMiddleware(),      // 认证
            RateLimitMiddleware(), // 限流
        )
        {
            api.GET("/users", listUsers)
        }

03.条件中间件
    a.动态应用
        func ConditionalAuth() gin.HandlerFunc {
            return func(c *gin.Context) {
                // 公开接口不需要认证
                publicPaths := []string{"/login", "/register", "/health"}

                for _, path := range publicPaths {
                    if c.Request.URL.Path == path {
                        c.Next()
                        return
                    }
                }

                // 其他接口需要认证
                AuthMiddleware()(c)
            }
        }

        router.Use(ConditionalAuth())

04.中间件复用
    a.工厂模式
        // 可配置的中间件工厂
        func CacheMiddleware(ttl time.Duration) gin.HandlerFunc {
            cache := make(map[string]cacheEntry)
            var mu sync.RWMutex

            return func(c *gin.Context) {
                key := c.Request.URL.Path

                mu.RLock()
                entry, exists := cache[key]
                mu.RUnlock()

                if exists && time.Now().Before(entry.expireAt) {
                    c.Data(200, "application/json", entry.data)
                    c.Abort()
                    return
                }

                c.Next()
            }
        }

        type cacheEntry struct {
            data     []byte
            expireAt time.Time
        }

        // 使用不同的TTL
        router.GET("/api/v1/data", CacheMiddleware(5*time.Minute), getData)
        router.GET("/api/v1/stats", CacheMiddleware(1*time.Minute), getStats)

5.5 错误处理中间件

01.统一错误处理
    a.错误捕获
        func ErrorHandlerMiddleware() gin.HandlerFunc {
            return func(c *gin.Context) {
                c.Next()

                // 检查是否有错误
                if len(c.Errors) > 0 {
                    err := c.Errors.Last()

                    // 根据错误类型返回不同响应
                    switch err.Type {
                    case gin.ErrorTypeBind:
                        c.JSON(400, gin.H{
                            "error": "参数错误",
                            "details": err.Error(),
                        })
                    case gin.ErrorTypePrivate:
                        c.JSON(500, gin.H{"error": "服务器错误"})
                    default:
                        c.JSON(500, gin.H{"error": err.Error()})
                    }
                }
            }
        }

02.panic恢复
    a.堆栈追踪
        func RecoveryWithStack() gin.HandlerFunc {
            return func(c *gin.Context) {
                defer func() {
                    if err := recover(); err != nil {
                        // 获取完整堆栈
                        stack := make([]byte, 4096)
                        length := runtime.Stack(stack, false)

                        log.Printf("[Panic] %v\n%s", err, stack[:length])

                        // 生产环境隐藏详情
                        if gin.Mode() == gin.ReleaseMode {
                            c.JSON(500, gin.H{"error": "服务器错误"})
                        } else {
                            c.JSON(500, gin.H{
                                "error": fmt.Sprintf("%v", err),
                                "stack": string(stack[:length]),
                            })
                        }

                        c.Abort()
                    }
                }()

                c.Next()
            }
        }

03.业务错误
    a.自定义错误
        type BusinessError struct {
            Code    int    `json:"code"`
            Message string `json:"message"`
        }

        func (e *BusinessError) Error() string {
            return e.Message
        }

        // 错误码定义
        var (
            ErrUserNotFound = &BusinessError{Code: 1001, Message: "用户不存在"}
            ErrInvalidParam = &BusinessError{Code: 1002, Message: "参数错误"}
            ErrUnauthorized = &BusinessError{Code: 1003, Message: "未授权"}
        )

        func BusinessErrorMiddleware() gin.HandlerFunc {
            return func(c *gin.Context) {
                c.Next()

                if len(c.Errors) > 0 {
                    err := c.Errors.Last().Err

                    if bizErr, ok := err.(*BusinessError); ok {
                        c.JSON(200, gin.H{
                            "code": bizErr.Code,
                            "message": bizErr.Message,
                        })
                    }
                }
            }
        }

04.错误响应
    a.环境区分
        func ErrorResponseMiddleware() gin.HandlerFunc {
            return func(c *gin.Context) {
                c.Next()

                if len(c.Errors) > 0 {
                    err := c.Errors.Last()

                    response := gin.H{
                        "error": err.Error(),
                        "path": c.Request.URL.Path,
                    }

                    // 开发环境显示详细信息
                    if gin.Mode() == gin.DebugMode {
                        response["type"] = err.Type
                        response["meta"] = err.Meta
                    }

                    c.JSON(500, response)
                }
            }
        }

5.6 认证授权中间件

01.JWT认证
    a.Token验证
        import "github.com/golang-jwt/jwt/v5"

        type Claims struct {
            UserID   int    `json:"user_id"`
            Username string `json:"username"`
            jwt.RegisteredClaims
        }

        func JWTMiddleware(secret string) gin.HandlerFunc {
            return func(c *gin.Context) {
                tokenString := c.GetHeader("Authorization")
                if tokenString == "" {
                    c.JSON(401, gin.H{"error": "未提供Token"})
                    c.Abort()
                    return
                }

                // 解析Token
                token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
                    return []byte(secret), nil
                })

                if err != nil || !token.Valid {
                    c.JSON(401, gin.H{"error": "Token无效"})
                    c.Abort()
                    return
                }

                claims := token.Claims.(*Claims)
                c.Set("user_id", claims.UserID)
                c.Set("username", claims.Username)

                c.Next()
            }
        }

02.Session认证
    a.Session管理
        import "github.com/gin-contrib/sessions"
        import "github.com/gin-contrib/sessions/cookie"

        func SessionMiddleware() gin.HandlerFunc {
            store := cookie.NewStore([]byte("secret-key"))
            return sessions.Sessions("mysession", store)
        }

        func AuthRequired() gin.HandlerFunc {
            return func(c *gin.Context) {
                session := sessions.Default(c)
                userID := session.Get("user_id")

                if userID == nil {
                    c.JSON(401, gin.H{"error": "未登录"})
                    c.Abort()
                    return
                }

                c.Set("user_id", userID)
                c.Next()
            }
        }

        // 登录
        router.POST("/login", func(c *gin.Context) {
            session := sessions.Default(c)
            session.Set("user_id", 123)
            session.Save()
            c.JSON(200, gin.H{"message": "登录成功"})
        })

03.OAuth2
    a.第三方登录
        import "golang.org/x/oauth2"
        import "golang.org/x/oauth2/github"

        var githubOAuth = &oauth2.Config{
            ClientID:     "your-client-id",
            ClientSecret: "your-client-secret",
            RedirectURL:  "http://localhost:8080/auth/github/callback",
            Scopes:       []string{"user:email"},
            Endpoint:     github.Endpoint,
        }

        router.GET("/auth/github", func(c *gin.Context) {
            url := githubOAuth.AuthCodeURL("state")
            c.Redirect(302, url)
        })

        router.GET("/auth/github/callback", func(c *gin.Context) {
            code := c.Query("code")
            token, err := githubOAuth.Exchange(context.Background(), code)
            if err != nil {
                c.JSON(500, gin.H{"error": "获取Token失败"})
                return
            }

            // 使用Token获取用户信息
            c.JSON(200, gin.H{"access_token": token.AccessToken})
        })

04.权限控制
    a.RBAC权限
        func RBACMiddleware(requiredRole string) gin.HandlerFunc {
            return func(c *gin.Context) {
                userRole := c.GetString("user_role")

                // 角色层级
                roleLevel := map[string]int{
                    "user":  1,
                    "admin": 2,
                    "super": 3,
                }

                if roleLevel[userRole] < roleLevel[requiredRole] {
                    c.JSON(403, gin.H{"error": "权限不足"})
                    c.Abort()
                    return
                }

                c.Next()
            }
        }

        // 使用
        router.GET("/admin/users",
            JWTMiddleware("secret"),
            RBACMiddleware("admin"),
            listUsers,
        )

6 高级特性

6.1 优雅关闭

01.信号处理
    a.优雅退出
        func main() {
            router := gin.Default()

            srv := &http.Server{
                Addr:    ":8080",
                Handler: router,
            }

            // 在goroutine中启动服务器
            go func() {
                if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
                    log.Fatalf("服务器启动失败: %v", err)
                }
            }()

            // 等待中断信号
            quit := make(chan os.Signal, 1)
            signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
            <-quit

            log.Println("关闭服务器...")

            // 5秒超时
            ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
            defer cancel()

            if err := srv.Shutdown(ctx); err != nil {
                log.Fatal("服务器强制关闭:", err)
            }

            log.Println("服务器已退出")
        }

02.连接关闭
    a.资源清理
        func GracefulShutdown(srv *http.Server, db *sql.DB, cache *redis.Client) {
            quit := make(chan os.Signal, 1)
            signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
            <-quit

            log.Println("开始优雅关闭...")

            // 关闭 HTTP 服务器
            ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
            defer cancel()

            if err := srv.Shutdown(ctx); err != nil {
                log.Printf("HTTP服务器关闭错误: %v", err)
            }

            // 关闭数据库连接
            if err := db.Close(); err != nil {
                log.Printf("数据库关闭错误: %v", err)
            }

            // 关闭 Redis 连接
            if err := cache.Close(); err != nil {
                log.Printf("Redis关闭错误: %v", err)
            }

            log.Println("所有资源已清理")
        }

6.2 性能优化

01.路由优化
    a.路由组织
        // 避免过深的路由嵌套
        // 不好:
        api := router.Group("/api")
        v1 := api.Group("/v1")
        users := v1.Group("/users")
        users.GET("/:id", getUser)

        // 好:
        router.GET("/api/v1/users/:id", getUser)

02.中间件优化
    a.按需加载
        // 只在需要的路由上使用中间件
        public := router.Group("/public")
        public.GET("/health", healthCheck)

        api := router.Group("/api")
        api.Use(AuthMiddleware())  // 只在 API 路由上认证
        api.GET("/users", listUsers)

03.序列化优化
    a.使用sonic
        import "github.com/bytedance/sonic"

        // 替换默认JSON序列化
        router.GET("/users", func(c *gin.Context) {
            users := getUsers()
            data, _ := sonic.Marshal(users)
            c.Data(200, "application/json", data)
        })

04.连接池
    a.数据库连接池
        db, err := sql.Open("mysql", dsn)

        // 设置连接池参数
        db.SetMaxOpenConns(100)                 // 最大连接数
        db.SetMaxIdleConns(10)                  // 最大空闲连接
        db.SetConnMaxLifetime(time.Hour)       // 连接最大生命周期
        db.SetConnMaxIdleTime(10 * time.Minute) // 空闲连接超时

6.3 测试

01.单元测试
    a.httptest测试
        func TestGetUser(t *testing.T) {
            router := gin.Default()
            router.GET("/users/:id", getUser)

            // 创建测试请求
            req, _ := http.NewRequest("GET", "/users/123", nil)
            w := httptest.NewRecorder()

            router.ServeHTTP(w, req)

            // 验证响应
            assert.Equal(t, 200, w.Code)

            var response map[string]interface{}
            json.Unmarshal(w.Body.Bytes(), &response)
            assert.Equal(t, float64(123), response["id"])
        }

02.集成测试
    a.完整流程测试
        func TestUserFlow(t *testing.T) {
            router := setupRouter()

            // 1. 注册
            registerReq := `{"username":"test","password":"123456"}`
            req, _ := http.NewRequest("POST", "/register", strings.NewReader(registerReq))
            req.Header.Set("Content-Type", "application/json")
            w := httptest.NewRecorder()
            router.ServeHTTP(w, req)
            assert.Equal(t, 201, w.Code)

            // 2. 登录
            loginReq := `{"username":"test","password":"123456"}`
            req, _ = http.NewRequest("POST", "/login", strings.NewReader(loginReq))
            req.Header.Set("Content-Type", "application/json")
            w = httptest.NewRecorder()
            router.ServeHTTP(w, req)
            assert.Equal(t, 200, w.Code)

            // 3. 获取token
            var loginResp map[string]string
            json.Unmarshal(w.Body.Bytes(), &loginResp)
            token := loginResp["token"]

            // 4. 访问受保护资源
            req, _ = http.NewRequest("GET", "/profile", nil)
            req.Header.Set("Authorization", "Bearer "+token)
            w = httptest.NewRecorder()
            router.ServeHTTP(w, req)
            assert.Equal(t, 200, w.Code)
        }

6.4 部署

01.编译部署
    a.Docker多阶段构建
        # Dockerfile
        FROM golang:1.21-alpine AS builder
        WORKDIR /app
        COPY go.mod go.sum ./
        RUN go mod download
        COPY . .
        RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

        FROM alpine:latest
        RUN apk --no-cache add ca-certificates
        WORKDIR /root/
        COPY --from=builder /app/main .
        EXPOSE 8080
        CMD ["./main"]

02.容器化
    a.镜像优化
        # 使用scratch最小镜像
        FROM scratch
        COPY --from=builder /app/main /main
        COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
        EXPOSE 8080
        CMD ["/main"]

03.配置管理
    a.环境变量
        import "github.com/spf13/viper"

        func LoadConfig() {
            viper.SetConfigName("config")
            viper.AddConfigPath(".")
            viper.AutomaticEnv()

            viper.ReadInConfig()

            port := viper.GetString("PORT")
            dbURL := viper.GetString("DATABASE_URL")
        }

6.5 最佳实践

01.项目结构
    a.分层架构
        project/
        ├── cmd/
        │   └── main.go
        ├── internal/
        │   ├── handler/
        │   ├── service/
        │   ├── repository/
        │   └── model/
        ├── pkg/
        ├── config/
        └── go.mod

02.错误处理
    a.统一错误码
        const (
            ErrCodeSuccess      = 0
            ErrCodeInvalidParam = 1001
            ErrCodeUnauthorized = 1002
            ErrCodeNotFound     = 1003
        )

7 实战案例

7.1 RESTful API

01.API设计
    a.CRUD完整示例
        // User CRUD API
        router.POST("/api/users", createUser)
        router.GET("/api/users", listUsers)
        router.GET("/api/users/:id", getUser)
        router.PUT("/api/users/:id", updateUser)
        router.DELETE("/api/users/:id", deleteUser)

        func listUsers(c *gin.Context) {
            page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
            pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))

            users, total := getUsersWithPage(page, pageSize)

            c.JSON(200, gin.H{
                "code": 0,
                "data": users,
                "page": gin.H{
                    "current": page,
                    "size": pageSize,
                    "total": total,
                },
            })
        }

7.2 认证系统

01.用户注册登录
    a.完整认证流程
        import "golang.org/x/crypto/bcrypt"

        // 注册
        router.POST("/register", func(c *gin.Context) {
            var req struct {
                Username string `json:"username" binding:"required"`
                Password string `json:"password" binding:"required,min=6"`
            }

            if err := c.ShouldBindJSON(&req); err != nil {
                c.JSON(400, gin.H{"error": err.Error()})
                return
            }

            // 密码加密
            hash, _ := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)

            user := createUser(req.Username, string(hash))
            c.JSON(201, gin.H{"user": user})
        })

        // 登录
        router.POST("/login", func(c *gin.Context) {
            var req struct {
                Username string `json:"username"`
                Password string `json:"password"`
            }

            c.ShouldBindJSON(&req)

            user := getUserByUsername(req.Username)
            if user == nil {
                c.JSON(401, gin.H{"error": "用户不存在"})
                return
            }

            // 验证密码
            if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)); err != nil {
                c.JSON(401, gin.H{"error": "密码错误"})
                return
            }

            // 生成JWT
            token := generateJWT(user.ID)
            c.JSON(200, gin.H{"token": token})
        })

7.3 文件服务

01.文件上传
    a.完整上传服务
        router.POST("/upload", func(c *gin.Context) {
            file, _ := c.FormFile("file")

            // 验证文件大小(10MB)
            if file.Size > 10*1024*1024 {
                c.JSON(400, gin.H{"error": "文件过大"})
                return
            }

            // 生成唯一文件名
            ext := filepath.Ext(file.Filename)
            filename := fmt.Sprintf("%d%s", time.Now().UnixNano(), ext)
            dst := filepath.Join("./uploads", filename)

            // 保存文件
            c.SaveUploadedFile(file, dst)

            c.JSON(200, gin.H{
                "url": "/uploads/" + filename,
                "size": file.Size,
            })
        })

7.4 WebSocket

01.连接管理
    a.WebSocket聊天室
        import "github.com/gorilla/websocket"

        var upgrader = websocket.Upgrader{
            CheckOrigin: func(r *http.Request) bool { return true },
        }

        type Hub struct {
            clients    map[*websocket.Conn]bool
            broadcast  chan []byte
            register   chan *websocket.Conn
            unregister chan *websocket.Conn
        }

        func (h *Hub) run() {
            for {
                select {
                case conn := <-h.register:
                    h.clients[conn] = true
                case conn := <-h.unregister:
                    delete(h.clients, conn)
                    conn.Close()
                case message := <-h.broadcast:
                    for conn := range h.clients {
                        conn.WriteMessage(websocket.TextMessage, message)
                    }
                }
            }
        }

        router.GET("/ws", func(c *gin.Context) {
            conn, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
            hub.register <- conn

            for {
                _, msg, err := conn.ReadMessage()
                if err != nil {
                    hub.unregister <- conn
                    break
                }
                hub.broadcast <- msg
            }
        })

7.5 微服务集成

01.服务注册发现
    a.Consul集成
        import "github.com/hashicorp/consul/api"

        func RegisterService() {
            config := api.DefaultConfig()
            client, _ := api.NewClient(config)

            registration := &api.AgentServiceRegistration{
                ID:      "gin-service-1",
                Name:    "gin-service",
                Port:    8080,
                Address: "localhost",
                Check: &api.AgentServiceCheck{
                    HTTP:     "http://localhost:8080/health",
                    Interval: "10s",
                    Timeout:  "3s",
                },
            }

            client.Agent().ServiceRegister(registration)
        }

        router.GET("/health", func(c *gin.Context) {
            c.JSON(200, gin.H{"status": "ok"})
        })