go语言框架 - Gin

gin.Engine 结构体

gin.Engine 是 Gin 框架中最重要的结构体,主要提供了以下功能:

  • 路由管理:注册和调度路由请求。

  • 中间件管理:添加、调用全局或局部中间件。

  • 服务启动:启动 HTTP 或 HTTPS 服务。

  • 静态资源管理:提供静态文件服务。

  • 错误处理:捕获和处理应用中的错误

gin.New()gin.Default()

Gin 提供了两个用于创建 Engine 实例的方法:

  1. gin.New()

    • 创建一个没有默认中间件的 Engine 实例。你需要手动添加所有中间件(例如日志和恢复中间件)

    r := gin.New()
  2. gin.Default()

    • 创建一个带有默认中间件的 Engine 实例。默认中间件包括 Logger(日志记录)和 Recovery(崩溃恢复)

    r := gin.Default()

    在大多数情况下,使用 gin.Default() 是比较方便的,因为它提供了一些基本的中间件,适合快速开发和调试。

Engine 的核心方法
1. 路由注册
  • GET/POST/PUT/DELETE/...

    • 用于注册不同的 HTTP 请求方法。每个方法对应一个处理函数。

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

  • 允许你为同一个路径注册所有的 HTTP 方法,GET/POST/PUT/DELETE/...

r.Any("/any", func(c *gin.Context) {
    c.String(200, "Any method accepted")
})
  • NoRoute()

  • 注册一个处理未匹配路径的路由处理函数,通常用于自定义 404 错误页面。

r.NoRoute(func(c *gin.Context) {
    c.JSON(404, gin.H{"message": "Not Found"})
})
2. 中间件管理
  • Use()

    • 添加全局中间件,所有请求都会经过这些中间件。

    r.Use(gin.Logger(), gin.Recovery())
3. 启动服务
  • Run()

    • 启动 HTTP 服务,默认监听在 :8080 端口。可以传入其他端口号或地址参数。

    r.Run()  // 监听并服务于 0.0.0.0:8080
  • RunTLS()

    • 启动 HTTPS 服务,要求提供 SSL 证书和密钥。

    r.RunTLS(":8080", "cert.pem", "key.pem")
  • RunUnix()

    • 启动 Unix 套接字服务。

    r.RunUnix("/tmp/gin.sock")
4. 静态文件和模板
  • Static()

    • 提供静态文件服务。可以将一个文件夹映射到一个路由前缀。

    r.Static("/assets", "./assets")

    静态文件通常指的是前端资源文件,如图片、CSS、JavaScript 文件等。Gin 提供了 Static() 方法,可以将一个目录映射到一个路由前缀,这样用户可以通过指定的 URL 路径访问这些文件。

    • /assets:URL 路径前缀。访问静态文件时,URL 必须以 /assets 开头。例如,http://localhost:8080/assets/logo.png 会访问 ./assets/logo.png 文件。

    • ./assets:本地文件系统中的目录路径。这个目录包含了静态资源文件,例如图片、CSS 文件等。

    package main
    
    import (
        "github.com/gin-gonic/gin"
    )
    
    func main() {
        r := gin.Default()
    
        // 提供静态文件服务,将本地的 ./assets 目录映射到 /assets 路径
        r.Static("/assets", "./assets")
    
        r.GET("/index", func(c *gin.Context) {
            c.String(200, "Welcome to the Index Page")
        })
    
        r.Run(":8080")
    }

    假设 ./assets 目录中有一个名为 logo.png 的图片文件,访问 http://localhost:8080/assets/logo.png 会返回这张图片。

  • LoadHTMLGlob()

    • 加载模板文件并渲染 HTML。支持通配符。

    r.LoadHTMLGlob("templates/*")

    在处理请求时,可以使用 c.HTML() 来渲染模板。

    r.GET("/index", func(c *gin.Context) {
        c.HTML(200, "index.tmpl", gin.H{"title": "Main website"})
    })

    Gin 也支持服务器端渲染 HTML 模板,这样你可以生成动态网页。模板文件通常是 .tmpl.html 文件,它们包含 HTML 和动态内容的占位符。

    • templates/\*:这个路径是模板文件的通配符,意味着 Gin 会加载 templates 目录下所有的模板文件。你可以在模板文件中使用 Go 的模板语法来动态生成内容。

    package main
    
    import (
        "github.com/gin-gonic/gin"
    )
    
    func main() {
        r := gin.Default()
    
        // 加载模板文件,支持通配符,表示加载 templates 目录下所有文件
        r.LoadHTMLGlob("templates/*")
    
        r.GET("/index", func(c *gin.Context) {
            // 渲染模板 index.tmpl,并传递一个包含动态数据的 map
            c.HTML(200, "index.tmpl", gin.H{
                "title": "Main website",
            })
        })
    
        r.Run(":8080")
    }

    假设你有一个模板文件 templates/index.tmpl,内容如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{{ .title }}</title>
    </head>
    <body>
        <h1>Welcome to {{ .title }}</h1>
    </body>
    </html>

    在这个例子中,c.HTML() 函数会渲染模板文件 index.tmpl,并将 gin.H{"title": "Main website"} 中的数据传递给模板。模板中的占位符 {{ .title }} 将被替换为 "Main website"

5. 错误处理
  • HandleContext()

    • 手动触发请求处理流程。在某些情况下,你可能需要手动处理上下文并将其传递给 Engine

    r.HandleContext(c)
  • AbortWithError()

    • 中止当前请求并记录错误。通常用于提前终止请求并返回错误信息。

    c.AbortWithError(500, errors.New("an error occurred"))

路由与路由组

Gin 提供了灵活的路由管理功能,你可以通过 GETPOSTPUTDELETE 等方法定义路由。路由组可以将相关的路由组织在一起,方便管理。

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",
        })
    })

    // 路由组
    v1 := r.Group("/v1")
    {
        v1.GET("/users", func(c *gin.Context) {
            // 处理 "/v1/users" 路由
        })
        v1.GET("/orders", func(c *gin.Context) {
            // 处理 "/v1/orders" 路由
        })
    }

    r.Run()
}

中间件

中间件是 Gin 框架的核心功能,用于在请求处理之前或之后执行特定操作。你可以定义全局中间件或为特定路由组定义中间件。

package main

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

// 定义一个简单的日志中间件
func Logger() gin.HandlerFunc {
    return func(c *gin.Context) {
        start := time.Now()

        // 处理请求
        c.Next()

        // 请求完成后执行
        duration := time.Since(start)
        log.Printf("Request processed in %s", duration)
    }
}

func main() {
    r := gin.Default()

    // 使用全局中间件
    r.Use(Logger())

    r.GET("/test", func(c *gin.Context) {
        c.String(200, "Hello, Gin!")
    })

    r.Run()
}

gin中自带一部分中间件比如gin.Logger()gin.Recovery()

gin.Logger()gin.Recovery() 是 Gin 框架中两个非常常用的全局中间件,它们用于处理日志记录和程序崩溃恢复。它们默认情况下会在 gin.Default() 初始化时自动加载。

1. gin.Logger()

gin.Logger() 是一个中间件,用于记录每个 HTTP 请求的日志信息,包括请求的路径、请求方法、状态码、处理时间等。

package main

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

func main() {
    // 使用 gin.Logger() 中间件
    r := gin.New()
    r.Use(gin.Logger())

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

    r.Run(":8080")
}

当你发送请求到 /ping 路径时,控制台会打印类似如下的日志:

[GIN] 2024/08/25 - 12:34:56 | 200 |    5.1234ms | 127.0.0.1 | GET /ping

日志记录了请求时间、状态码、请求处理时间、客户端 IP 地址、请求方法和路径等信息。

2. gin.Recovery()

gin.Recovery() 是一个中间件,用于在程序出现 panic 时进行恢复,避免程序崩溃并返回 500 错误。Gin 提供了 Recovery 中间件来捕获 panic 并记录错误信息,然后返回一个友好的 HTTP 500 错误页面或 JSON 响应,而不会导致整个服务挂掉。

package main

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

func main() {
    // 使用 gin.Recovery() 中间件
    r := gin.New()
    r.Use(gin.Recovery())

    r.GET("/panic", func(c *gin.Context) {
        // 模拟一个会引发 panic 的操作
        panic("Something went wrong!")
    })

    r.Run(":8080")
}

当访问 /panic 路径时,程序会引发 panic。由于使用了 gin.Recovery() 中间件,程序不会崩溃,而是捕获 panic 并返回 500 错误。控制台会记录如下的错误日志:

[GIN] 2024/08/25 - 12:34:56 | 500 |    10.5678ms | 127.0.0.1 | GET /panic
[GIN-debug] [Recovery] 2024/08/25 - 12:34:56 panic recovered:
runtime error: Something went wrong!

gin.context

在 Gin 框架中,gin.Context 是核心结构体,它封装了 HTTP 请求和响应,并提供了丰富的功能来处理 HTTP 请求的各种操作。gin.Context 提供了对路由、参数、请求数据、中间件等方面的管理,是 Gin 中用于处理请求的主要对象。

gin.Context 的主要功能
1. 获取请求数据
  • 查询参数

    • 使用 Query() 方法获取 URL 中的查询参数。

    • 如果查询参数不存在,可以指定默认值。

    c.Query("name")           // 获取查询参数 name 的值
    c.DefaultQuery("name", "default_name") // 获取查询参数 name 的值,若不存在则返回默认值 "default_name"
  • 表单参数

    • 使用 PostForm() 方法获取 POST 请求中的表单数据。

    c.PostForm("name")
    c.DefaultPostForm("name", "default_name")
  • 路径参数

    • 使用 Param() 方法获取路由中定义的路径参数。

    c.Param("id")  // 例如: 路由定义为 "/user/:id"
  • JSON 数据

    • 使用 ShouldBindJSON()BindJSON() 解析 JSON 数据并绑定到结构体。

    var jsonData MyStruct
    if err := c.ShouldBindJSON(&jsonData); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
2. 设置和获取上下文中的数据
  • 设置数据

    • 使用 Set() 方法在 gin.Context 中存储数据,供后续的处理中使用。

    c.Set("key", "value")
  • 获取数据

    • 使用 Get() 方法获取上下文中的数据。还可以使用 GetString()GetInt() 等辅助方法进行类型转换。

    value, exists := c.Get("key")
3. 响应处理
  • 返回 JSON 响应

    c.JSON(200, gin.H{
        "message": "Hello, World!",
    })
  • 返回字符串响应

    c.String(200, "Hello, %s", name)
  • 返回文件响应

    c.File("./path/to/file")
  • 返回重定向

    c.Redirect(302, "/new_path")
4. 中间件处理

gin.Context 中的中间件功能允许你在处理请求之前或之后执行一些操作,例如日志记录、授权、请求修改等。

  • 在中间件中处理

    func MyMiddleware() gin.HandlerFunc {
        return func(c *gin.Context) {
            // 执行操作,例如设置上下文中的数据
            c.Set("example", "value")
    ​
            // 执行下一步操作
            c.Next()
    ​
            // 在请求处理后执行操作
            status := c.Writer.Status()
            log.Println("Status:", status)
        }
    }
  • 中止请求

    • 使用 Abort() 方法停止请求的进一步处理,并立即返回响应。

    c.AbortWithStatus(403)
5. 控制流管理

gin.Context 提供了对请求生命周期的控制,包括中止请求、跳过中间件等。

  • Next()

    • Next() 方法让控制流继续到下一个中间件或最终处理器。通常用于中间件链中。

    c.Next()
  • Abort()AbortWithStatus()

    • Abort() 用于停止控制流,并且不会继续调用后续的中间件或处理器。

    • AbortWithStatus() 可以在中止请求的同时返回 HTTP 状态码。

    c.Abort()
    c.AbortWithStatus(400)
6. 文件上传

Gin 提供了对文件上传的简便支持,允许通过 gin.Context 直接处理文件上传请求。

// 单文件上传
file, _ := c.FormFile("file")
c.SaveUploadedFile(file, "./uploads/"+file.Filename)
​
// 多文件上传
form, _ := c.MultipartForm()
files := form.File["files"]
for _, file := range files {
    c.SaveUploadedFile(file, "./uploads/"+file.Filename)
}

context.Contextgin.Context

gin.Context 实现了 Go 语言的 context.Context 接口,因此你可以在 Gin 的上下文中使用标准的 context.Context 方法,如 Deadline()Done()Err()Value()。这意味着你可以利用 gin.Context 的功能在并发环境下传递取消信号、超时等信息。

r.GET("/timeout", func(c *gin.Context) {
    // 创建一个带超时的 context
    ctx, cancel := context.WithTimeout(c.Request.Context(), 2*time.Second)
    defer cancel()
​
    select {
    case <-time.After(3 * time.Second):
        // 模拟长时间运行任务
        c.String(http.StatusOK, "Completed after 3 seconds")
    case <-ctx.Done():
        // 超时或取消
        c.String(http.StatusRequestTimeout, "Request timed out")
    }
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值