聊一聊Go的Context上下文

本文探讨了Go语言中的Context上下文,包括为何需要Context、如何解决协程泄露问题,以及Context在管理子协程生命周期、控制请求超时等方面的应用。通过示例展示了Context的使用方法,强调了其在传递请求作用域数据和限制上下文滥用的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Context

前言

前面在“聊一聊http框架httprouter”的时候,有提到上下文的概念,上一个demo用来列举web框架中全局变量的传值和设置,还类比了Java Spring框架中ApplicationContext
这一次我们就来聊一聊Go中的标准库的context,梳理上下文概念在go中的常用情景。

问题引入

在列举上下文的用法之前,我们来看一个简单的示例:

协程泄露
func main()  {
   
	//打印已有协程数量
	fmt.Println("Start with goroutines num:", runtime.NumGoroutine())
	//新起子协程
	go Spawn()
	time.Sleep(time.Second)
	fmt.Println("Before finished, goroutines num:", runtime.NumGoroutine())
	fmt.Println("Main routines exit!")
}

func Spawn()  {
   
	count := 1
	for {
   
		time.Sleep(100 * time.Millisecond)
		count++
	}
}

输出:

Start with goroutines num: 1
Before finished, goroutines num: 2
Main routines exit!

我们在主协程创建一个子协程,利用runtime.NumGoroutine()打印当前协程数量,可以知道在main协程被唤醒之后退出前的那一刻,程序中仍然存在两个协程,可能我们已经习惯了这种现象,杀掉主协程的时候,退出会附带把子协程干掉,这种让子协程“自生自灭”的做法,其实是不太优雅的。

解决方式

管道通知退出

关于控制子协程的退出,可能有人会想到另一个做法,我们再来看另一个例子。

func main()  {
   
	defer fmt.Println("Main routines exit!")
	ExitBySignal()
	fmt.Println("Start with goroutines num:", runtime.NumGoroutine())
	//主动通知协程退出
	sig <- true
	fmt.Println("Before finished, goroutines num:", runtime.NumGoroutine())
}

//利用管道通知协程退出
func ListenWithSignal()  {
   
	count := 1
	for {
   
		select {
   
		//监听通知
		case <-sig:
			return
		default:
			//正常执行
			time.Sleep(100 * time.Millisecond
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值