初识Gin,项目没你可不行 | 青训营

214 阅读8分钟

通过Gin搭建Go-Web应用程序

一、基本概念

Gin 是一个用Go 语言实现的 Web 应用程序的轻量级框架,具有接口简洁,性能极高的特征,旨在提供快速而灵活的方式来处理 HTTP 请求、路由和中间件等。它有如下一些特点和重要概念:

轻量级高性能快速路由中间件JSON 支持参数绑定和验证错误管理分组路由HTML 模板性能优化


二、简单实现

我们先提供一个简单的gin示例

package main  
  
import (  
    "github.com/gin-gonic/gin"  
)  
  
func main() {  
    // 创建一个默认的路由引擎  
    r := gin.Default()  
    // GET:请求方式;/hello:请求的路径  
    // 当客户端以GET方法请求/hello路径时,会执行后面的匿名函数  
    r.GET("/hello", func(c *gin.Context) {  
    // c.JSON:返回JSON格式的数据  
        c.JSON(200, gin.H{  
            "message": "Hello, Gin!",  
        })  
    })
// 启动HTTP服务,默认在0.0.0.0:8080启动服务  
    r.Run()  
}

开始逐行分析!

3 - 安装与导包

go get -u github.com/gin-gonic/gin

9 - 创建默认的 Gin 路由引擎

r := gin.Default()

这里创建了一个默认的路由引擎 r,使用了 Gin 框架的默认中间件,包括请求日志记录和恢复。

12 - GET 请求的路由处理函数

r.GET("/hello", func(c *gin.Context) { ... })

这段代码定义了一个 GET 请求的路由。当客户端发起 GET 请求到 /hello 路径时,会执行匿名函数。

c *gin.Context 是 Gin 框架中的一个核心概念,表示请求的上下文(Context)。它是一个结构体指针,封装了关于当前 HTTP 请求的所有信息,包括请求参数、路由信息、响应数据等。在处理请求时,你可以通过访问 c 来访问和操作请求的各个方面。

14-15 - 在匿名函数中,使用 c.JSON 返回 JSON 格式的数据

c.JSON(200, gin.H{ ... })

这里返回一个 HTTP 状态码为 200 的 JSON 响应(成功处理了请求),包含一个键值对,其中键为 "message",值为 "Hello, Gin!"。

19 - 启动 HTTP 服务

r.Run()
r.Run(":8000")//此处指可以在8000端口上运行此项目

这行代码启动 HTTP 服务,默认监听在 0.0.0.0:8080 地址上,等待客户端连接。

这里使用 Gin 框架创建了一个简单的 HTTP 服务器,当客户端访问/hello路径时,会返回一个 JSON 格式的 "Hello, Gin!" 消息。

此时进入http://localhost:8080/hello,看到信息则为启动成功。


三、基本功能

路由定义

在 Gin 框架中,路由定义是指将 URL 路径映射到相应的处理函数,以便根据客户端发起的请求来执行特定的操作。Gin 支持常见的 HTTP 请求方法(GET、POST、PUT、DELETE 等),可以根据不同的请求方法来定义相应的路由。

r.GET("/hello", func(c *gin.Context) {
    // 处理 GET /hello 请求的代码
})

r.POST("/create", func(c *gin.Context) {
    // 处理 POST /create 请求的代码
})

r.PUT("/update/:id", func(c *gin.Context) {
    // 处理 PUT /update/:id 请求的代码
})

r.DELETE("/delete/:id", func(c *gin.Context) {
    // 处理 DELETE /delete/:id 请求的代码
})

在上述示例中,每个方法的第一个参数是一个字符串,表示要匹配的 URL 路径。当客户端发起对应的 HTTP 请求时,Gin 框架将调用指定的处理函数,这个函数的参数是一个 gin.Context 对象,通过它可以访问请求信息和构建响应。

小插一嘴(PUT/DELETE 请求)

PUT 请求通常用于更新资源,即向服务器发送一个包含更新后数据的请求,服务器将该数据用于更新相应的资源。

DELETE 请求通常用于删除资源,即告诉服务器删除指定的资源。

当客户端发送一个PUT(DELETE)请求/update/:id(/delete/:id)路径时,与之匹配的处理函数将会被执行。在函数中,你可以使用c.Param来获取 URL 路径参数,然后执行相应的更新(删除)操作。


请求的上下文

c *gin.Context 是 Gin 框架中的一个核心概念,表示当前 HTTP 请求的上下文。通过这个上下文对象,你可以获取请求的各种信息,操作响应,以及与中间件和处理函数进行交互。以下是一些常见的 c *gin.Context 的用法示例:


获取 URL 路径参数:

使用 c.Param 方法来获取 URL 路径参数。

r.GET("/user/:id", func(c *gin.Context) { 
    id := c.Param("id") 
    c.String(http.StatusOK, "id=%s", id) 
})

如果想要获取不止一个参数,则需要使用 c.Params 属性,该属性是一个包含了所有的参数的数组。相当于先 c.Params 然后组合到一起。

r.GET("/user/:id/:name", func(c *gin.Context) {
    id := c.Param("id")
    name := c.Param("name")
    params := c.Params
    c.String(http.StatusOK, "id=%s, name=%s, params=%v", id, name, params)
})

image.png

image.png

这里定义了一个路由 /user/:id/:name,通过 c.Params 方法可以获取所有参数的值。需要注意的是,c.Params 方法返回的是一个数组,其中每个元素是一个 gin.Param 结构体,包含了参数的键值对信息。可以通过 KeyValue 属性分别获取键和值


获取查询参数:

使用 c.Query 方法来获取 URL 查询参数。 当处理 HTTP 请求时,查询参数(Query Parameters)是附加在 URL 后面的键值对,用于向服务器传递额外的数据或参数

假设有一个请求的URL:

http://example.com/search?term=apple&type=fruit

我们可以使用 c.Query 方法来获取查询参数的值。

func SearchHandler(c *gin.Context) {
    term := c.Query("term") // 获取查询参数 "term" 的值,结果为 "apple"
    typeParam := c.Query("type") // 获取查询参数 "type" 的值,结果为 "fruit"
    
    c.JSON(http.StatusOK, gin.H{
        "term": term,
        "type": typeParam,
    })
}

如果不确定是否有数据可以使用c.DefaultQuery,在没数据时返回默认值

func SearchHandler(c *gin.Context) {
    // 获取查询参数 "q" 的值,如果不存在则返回 "default"
    searchTerm := c.DefaultQuery("q", "default") 
    c.String(http.StatusOK, "Search term: %s", searchTerm)
}

获取 POST 表单参数:

使用 c.PostForm 从 HTTP POST 请求的表单数据中获取指定名称的参数值

假设客户端发送了一个 POST 请求,包含以下表单数据:

name=John&age=30&email=john@example.com

在处理函数中,你可以使用 c.PostForm 方法来获取这些表单字段的值。

func FormHandler(c *gin.Context) {
    name := c.PostForm("name") // 获取表单字段 "name" 的值,结果为 "John"
    age := c.PostForm("age") // 获取表单字段 "age" 的值,结果为 "30"
    email := c.PostForm("email") // 获取表单字段 "email" 的值,结果为 "john@example.com"
    
    c.JSON(http.StatusOK, gin.H{
        "name":  name,
        "age":   age,
        "email": email,
    })
}

c.DefaultPostForm()用于设定默认值,与上面同理


绑定 JSON 请求数据:

使用 c.ShouldBindJSON 方法将 JSON 请求体绑定到一个 Go 结构体。

var user User
if err := c.ShouldBindJSON(&user); err == nil {
    // 对 user 进行处理
}

如果想要适用多种格式,可以使用 ShouldBindBodyWith (可以根据请求的 Content-Type 头部,灵活地选择绑定方式)

具体可以看:

Golang Gin 优雅地解析JSON请求数据(ShouldBindBodyWith避免出现EOF错误)


其他处理提交客户端提交参数的方法:

  • c.GetHeader():获取客户端提交的请求头信息。

  • c.GetRawData():获取客户端提交的请求体信息(原始数据)。

  • c.Request.FormValue():获取客户端提交的表单参数值。

  • c.Request.PostFormValue():获取客户端提交的 POST 请求参数值。


构建 JSON 响应:

使用 c.JSON 方法来构建 JSON 格式的响应。

c.JSON(http.StatusOK, gin.H{"message": "Success"})

构建 HTML 响应:

使用 c.HTML 方法来构建 HTML 格式的响应。

c.HTML(http.StatusOK, "<h1>Hello, Gin!</h1>")

构建纯文本响应:

使用 c.String 方法来构建纯文本格式的响应。

c.String(http.StatusOK, "Hello, Gin!")

设置响应状态码:

使用 c.Status 方法来设置响应的 HTTP 状态码。

c.Status(http.StatusNotFound)

中止请求处理:

使用 c.Abort 方法来中止请求处理过程,终止后续的中间件和处理函数的执行。

这个方法通常用于在中间件或处理函数中检测到错误或特定条件时,提前终止请求的处理,避免继续执行后续代码

  1. 错误处理

    当在处理请求时发生错误,你可以使用 c.Abort() 来中止请求的处理流程,然后返回相应的错误响应。

    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": "Internal Server Error"})
        c.Abort()
        return
    }
    
  2. 认证和授权

    在进行认证或授权检查时,如果用户未通过验证或没有权限,可以中止请求的处理。

    if !isAuthorized {
        c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
        c.Abort()
        return
    }
    
  3. 其他条件检查

    你可以根据其他任何条件来决定是否中止请求的处理流程,以避免不必要的计算或操作。

    if someCondition {
        c.JSON(http.StatusBadRequest, gin.H{"error": "Bad Request"})
        c.Abort()
        return
    }
    

传递到下一个处理函数:

使用 c.Next 方法来将请求传递到下一个中间件或处理函数。

func Middleware(c *gin.Context) {
    // 执行一些操作
    c.Next() // 将请求传递到下一个中间件或处理函数
}

通过 c *gin.Context,你可以访问请求的各种信息、构建响应、中止请求处理、以及与中间件和处理函数进行交互,从而实现各种功能和操作。


HTTP状态码

使用 c.Status 方法来设置响应的 HTTP 状态码。

c.Status(http.StatusOK) // 设置状态码为 200 OK

使用 c.JSON 方法来返回 JSON 格式的响应,可以将状态码和响应内容一起设置。

c.JSON(http.StatusNotFound, gin.H{"message": "Not Found"}) // 返回状态码 404 和响应内容

使用 c.String 方法来返回纯文本格式的响应。

c.String(http.StatusInternalServerError, "Internal Server Error") // 返回状态码 500 和响应

状态码大全

HTTP - 状态 | Status - 开发者手册 - 腾讯云开发者社区-腾讯云 (tencent.com)

点到为止

篇幅已经很长了,这篇文章就到这里吧。像相对复杂一点的中间件,或是在项目中运用的文件上传、Cookie、Session等,我们就放在下一篇吧,敬请期待 (づ●─●)づ

感谢阅读,觉得文章不错的话可以赏个赞吖ლ(^ω^ლ)

参考文章: