gin 七.路由组与接口异步处理的注意事项

文章介绍了Gin框架中路由组的概念和使用,如管理相同前缀的路由、创建子路由组以及应用中间件。同时,讨论了异步处理的注意事项,强调在开启goroutine时需使用c.Copy创建只读上下文副本,以及在异步操作中应考虑的数据一致性、并发控制和错误处理问题。
摘要由CSDN通过智能技术生成

一. 路由组

  1. 什么是路由组: gin框架中通过路由组可以管理相同前缀的多个路由方法。方便进行统一的处理和管理

例如,可以将所有以/v1开头的路由归类到一个名为v1的路由组中,表示这些路由都是版本1的接口。也可以将所有以/admin开头的路由归类到一个名为authorized的路由组中,表示这些路由都需要身份验证。

  1. gin框架提供了r.Group(relativePath string, handlers …HandlerFunc)用于创建一个路由组。这个方法接受两个参数:relativePath表示路由组的相对路径,handlers表示可选的中间件函数
import (
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
)

func CreateRouter() *gin.Engine {
	//获取默认RouterRouter
	router := gin.Default()
	//兜底的路由
	router.NoRoute(errFunc)

	//1.通过Router调用Grout("/")设置路由组
	shopGroup := router.Group("/shop")
	{
		//2.通过路由组返回的*RouterGroup注册路由
		shopGroup.GET("/index", func(c *gin.Context) {...})
		shopGroup.GET("/cart", func(c *gin.Context) {...})
		shopGroup.POST("/checkout", func(c *gin.Context) {...})
		shopGroup.Post("/multFile",MultipartFuncs)
		
		// 3.路由组中可以继续嵌套路由组
		xx := shopGroup.Group("xx")
		xx.GET("/oo", func(c *gin.Context) {...})
	}
	
	return router
}
  1. 我们也可以在创建路由组时传入一些中间件函数,它们会作用于该路由组下的所有路由
func main() {
	r := gin.Default() // 创建一个默认的gin引擎
	// 创建一个名为authorized的路由组,它的相对路径是/admin,并且使用AuthRequired中间件
	authorized := r.Group("/admin", AuthRequired())
	{
		// 在authorized路由组下注册一个GET路由
		authorized.GET("/dashboard", dashboardHandler)
	}

	r.Run(":8080") // 启动服务器
}
  1. 并且gin框架支持在一个路由组下创建子路由组,实现嵌套和继承的效果。子路由组会继承父路由组的相对路径和中间件,并且可以添加自己的相对路径和中间件。

二. 异步处理注意事项

  1. 解释,在请求后端接口时,某些情况下可能需要直接响应成功,后端异步去执行其他操作,此时直接通过groutine开启一个协程即可(接口默认是同步等待的),但是有几个注意点
  1. 在启动新的goroutine时,一定要使用c.Copy方法创建一个只读的上下文副本,否则可能会导致数据竞争或内存泄漏。
  2. 在异步处理完成后,如果想要返回响应,一定要使用r.HandleContext函数将请求转发到另一个路由函数,否则可能会导致响应头或响应体被写入多次或无法写入。
  3. 在异步处理中,如果需要访问数据库或外部服务,一定要使用合适的并发控制或连接池机制,否则可能会导致资源耗尽或性能下降。
  4. 在异步处理中,如果需要处理错误或异常情况,一定要使用合适的错误处理或恢复机制,否则可能会导致程序崩溃或数据丢失

Context.Copy

  1. 注意点,由于groutine是异步的,防止Context数据在groutine外部使用造成数据混乱所以在groutine中不可修改Context的值,通常情况下是复制一个Context的副本拿来使用
import (
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"time"
)

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

	//1. 注册路由(默认同步的)
	r.GET("/long_sync", func(c *gin.Context) {
		time.Sleep(5 * time.Second)
		// 注意可以使⽤原始上下⽂
		log.Println("Done! in path " + c.Request.URL.Path)
	})

	//1. 异步,在AsyncTest函数中直接响应结果,然后通过goroutine异步执行,
	r.GET("/long_async", AsyncTest)

	// Listen and serve on 0.0.0.0:8080
	r.Run(":8080")
}

func AsyncTest(c *gin.Context) {
	//1.复制出一份只读的Context供goroutine中使⽤ 
	cCp := c.Copy()
	//2.开启goroutine异步执行逻辑
	go func() {
		time.Sleep(5 * time.Second)
		// 注意使⽤只读上下⽂
		log.Println("Done! in path " + cCp.Request.URL.Path)
	}()
	//此处直接响应
	c.JSON(http.StatusOK, gin.H{"data": "成功响应的数据"})
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在使用 Gin 框架时,可以使用 `gin.Context` 对象来控制接口的行为。可以将一个 `context.Context` 对象作为参数传递给接口,然后在接口的实现中,使用 `gin.Context` 对象来检查是否有取消信号。如果有取消信号,那么接口会被取消。 下面是一个使用 Gin 框架的示例代码,演示了如何使用 `gin.Context` 来取消一个正在运行的接口: ```go import ( "context" "github.com/gin-gonic/gin" ) func longRunningOperation(ctx context.Context) error { for { // 检查是否有取消信号 select { case <-ctx.Done(): return ctx.Err() default: // 执行操作 } } } func main() { r := gin.Default() r.GET("/operation", func(c *gin.Context) { // 创建一个 context.Context 对象 ctx, cancel := context.WithCancel(context.Background()) // 启动一个长时间运行的操作 go func() { err := longRunningOperation(ctx) if err != nil { c.AbortWithError(http.StatusInternalServerError, err) return } c.JSON(http.StatusOK, gin.H{"message": "Operation completed"}) }() // 在某个时间点取消操作 time.Sleep(10 * time.Second) cancel() }) r.Run(":8080") } ``` 在这个示例中,我们使用 Gin 框架创建了一个 HTTP 服务,并定义了一个 GET 接口 `/operation`。在这个接口的实现中,我们首先创建了一个 `context.Context` 对象,并使用 `context.WithCancel` 函数初始化它。然后,我们启动了一个长时间运行的操作,并将 `context.Context` 对象传递给它。在操作完成后,我们将一个 JSON 响应返回给客户端。 最后,在一个等待时间后,我们调用了 `cancel()` 方法,以取消操作。在实际应用中,取消操作可能会根据特定的业务逻辑来触发。注意,在这个示例中,我们使用了 `time.Sleep` 函数来模拟一个等待时间。在实际应用中,应该避免在 HTTP 请求处理中使用 `time.Sleep` 函数,以免阻塞整个服务器的请求处理能力。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值