Go Gin框架
:dancer: Gin前言
Gin 是一个流行的 Go 语言 Web 框架
:one: 处理前端传来的数据
1. 获取 URL 参数
URL 参数通常用于 GET 请求,可以通过 c.Param 获取。
- Gin 框架中的 GET 请求,如果需要从 URL 中获取参数,则要在 URL 路由中指定参数。这些参数在 URL 中以冒号 : 开头
r.GET("/user/:name", func(c *gin.Context) {
name := c.Param("name")
c.String(http.StatusOK, "Hello %s", name)
})2. 获取 Query 参数
Query 参数也是用于 GET 请求,可以通过 c.Query 或 c.DefaultQuery 获取。
c.Query("firstname")是从 HTTP GET 请求的查询参数中获取名为 “firstname” 的参数值。http://example.com/welcome?firstname=John&lastname=Doe- 查询参数通常在 URL 中以 ? 开始,每个参数以 & 分隔,
c.Query和c.DefaultQuery都是用于从 HTTP GET 请求的查询参数中获取值的方法,- 但它们在处理不存在的参数时的行为不同。
c.Query("paramName")会尝试获取名为"paramName"的查询参数的值。如果该参数不存在,它将返回空字符串。c.DefaultQuery("paramName", "defaultValue")也会尝试获取名为"paramName"的查询参数的值。但是,如果该参数不存在,它将返回提供的默认值"defaultValue",而不是空字符串。r.GET("/welcome", func(c *gin.Context) { firstname := c.Query("firstname") lastname := c.DefaultQuery("lastname", "Guest") c.String(http.StatusOK, "Hello %s %s", firstname, lastname) })
- 但它们在处理不存在的参数时的行为不同。
3. 获取 POST 表单数据
POST 请求的表单数据可以通过 c.PostForm 或 c.DefaultPostForm 获取。(区别同理,是否提供默认值)
r.POST("/form_post", func(c *gin.Context) {
message := c.PostForm("message")
nick := c.DefaultPostForm("nick", "anonymous")
c.JSON(http.StatusOK, gin.H{
"status": "posted",
"message": message,
"nick": nick,
})
})4. 获取 JSON数据
对于 JSON数据,可以使用 c.BindJSON 或 c.ShouldBindJSON 将 JSON数据绑定到结构体。
- 默认选择
c.ShouldBindJSON(更灵活)
type Login struct {
User string `json:"user" binding:"required"`
Password string `json:"password" binding:"required"`
}
r.POST("/login", func(c *gin.Context) {
var `JSON `Login
if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if json.User != "admin" || json.Password != "admin" {
c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
})5. 获取 Header 信息
可以通过 c.GetHeader 获取请求头信息。
r.GET("/header", func(c *gin.Context) {
ua := c.GetHeader("User-Agent")
c.String(http.StatusOK, ua)
})6. 获取文件上传
文件上传可以通过 c.FormFile 获取,并保存到服务器上。
r.POST("/upload", func(c *gin.Context) {
file, _ := c.FormFile("file")
c.SaveUploadedFile(file, "uploads/" + file.Filename)
c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
})file, _ := c.FormFile("file"):
c.FormFile方法用于从 POST 请求中获取上传的文件。"file"是 HTML 表单中的<input type="file" name="file">的字段名称。- 这行代码将上传的文件赋值给
file变量。第二个返回值是可能的错误,但在这个例子中被忽略了(用_表示)。
c.SaveUploadedFile(file, "uploads/" + file.Filename):
c.SaveUploadedFile方法用于将上传的文件保存到服务器上的指定路径。file是从表单中获取的文件对象,"uploads/" + file.Filename是文件保存的路径。file.Filename是上传文件的原始文件名。- 在这个例子中,文件将被保存到
uploads目录下,文件名保持不变。
:two: 返回响应给前端
1. 返回字符串
用于简单的文本或消息。
c.String(http.StatusOK, "Hello, World!")2. 返回 JSON
用于返回结构化的 JSON 数据,通常用于 API 响应。
c.JSON(http.StatusOK, gin.H{
"message": "Hello, World!",
"status": "success",
}):three: 存取上下文变量
在 Go 的 Gin 框架中,c.GetInt64("uid") 是从 Gin 的上下文(*gin.Context)中获取 uid 的值。这个 uid 是一个从请求中提取或设置的值,通常是在处理 HTTP 请求时的中间件或处理函数中进行存储的。
如何存储到上下文中?
通常,uid 可能会通过以下几种方式存储到 Gin 上下文中:
中间件中存储:
在请求处理链中的某个中间件函数中,
uid被提取出来(例如,从请求头、查询参数、Cookie 中等),然后使用c.Set("uid", uid)存储到上下文中。示例:
func AuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { uid := extractUIDFromRequest(c) // 假设你有个函数来提取 uid c.Set("uid", uid) c.Next() } }- 另外,关于
c.Next()c.Next()被用在 JWT 中间件中。这个中间件首先检查请求的 Authorization 头来验证 JWT。- 如果验证成功,它会将用户 ID 设置到上下文中,然后调用 c.Next() 来启动后续的处理函数。
- 如果验证失败,它会直接返回一个错误响应,不会调用 c.Next(),所以后续的处理函数不会被执行。
- 另外,关于
在处理函数中存储:
有时
uid可能会在请求处理函数中直接存储到上下文中,尤其是在处理特定的请求时,可能需要动态设置上下文的值。示例:
func SomeHandler(c *gin.Context) { uid := getUIDFromSomewhere() // 从某处获取 uid c.Set("uid", uid) // 继续处理请求 }
有效期是什么时候?
uid 的有效期是与当前请求的生命周期相同的。也就是说:
- 请求生命周期:当一个 HTTP 请求到达时,一个新的
*gin.Context实例会被创建并与请求相关联。所有在请求处理中存储在上下文中的数据(包括uid)都只在这个请求的生命周期内有效。 - 处理完成:一旦请求处理完成,
*gin.Context实例就会被销毁,存储在其中的数据也会丢失。下一个请求会创建一个新的*gin.Context实例,所以uid的值不会在不同请求之间保持。
:four:上下文处理
context.Background():- 作用:它返回一个空的上下文(context),这个上下文永远不会被取消,也没有存储值,也没有设定任何截止时间。它通常作为其他上下文的基础上下文。
- 使用场景:当你需要一个不需要取消或进一步控制的基础上下文时,可以使用它。通常在不需要取消或超时控制的顶级函数调用中使用。
context.WithCancel(context.Background()):- 作用:这个函数返回一个从
context.Background()派生出来的上下文,并返回一个cancel函数。你可以调用这个cancel函数来取消上下文。 - 使用场景:当你需要能够取消上下文的功能时使用。例如,当你启动一个可能需要在某个时间点停止的 goroutine 时,可以将这个可取消的上下文传递给 goroutine,并在需要停止时调用
cancel函数。
- 作用:这个函数返回一个从
为什么需要使用上下文(Context)?
- 取消操作:上下文用于管理并发操作的生命周期,特别是在涉及多个 goroutine 时,能够通过上下文传递取消信号来安全地停止这些操作。