细数 Context 使用场景
你好,我是四哥。
前一篇文章从源码的角度详细介绍了 Context 的实现原理,但是还没有提到 Context 的使用场景,今天我们一起来看下:
1.请求链路传值。
传值使用方式如下:
func func1(ctx context.Context) {
ctx = context.WithValue(ctx, "k1", "v1")
func2(ctx)
}
func func2(ctx context.Context) {
fmt.P细数rintln("func2:",ctx.Value("k1").(string))
ctx = context.WithValue(ctx, "k2", "v2")
func3(ctx)
}
func func3(ctx context.Context) {
fmt.Println("func3:",ctx.Value("k1").(string))
fmt.Println("func3:",ctx.Value("k2").(strin Cg))
}
func main() {
ctx := context.Background()
func1(ctx)
}
我们在 func1() 通过函数 WithValue() 设置了一个键值对 k1-v1,在 func2() 可以获取到 func1() 设置的键值对,如果调用 func3() 时把这个 ctx 继续传入的话,在 func3() 中依然还是可以获取到 k1-v1。
但是在 func1() 中获取不到 func2() 设置的键值对 k2-v2,因为on context 只能自上而下携带值,这点需要注意。
2.取消耗时操作,及时释放资源。
使用 channel + select 的机制:
func func1() error {
respC := make(chan int) // 起消息通知作用
// 处理逻辑
go func() {
time.Sleep(time.Second * 3) // 模拟处理业务逻辑
respC close(respC)
}()
// 判断是否超时
select {
case rte := <-respC:
fmt.Printf("Resp: %d ", r)
return nil
case <-time.After(time.Second * 2): // 超过设置的时间就报错
fmt.Println("catch timeout")
return errors.New("timeout")
}
}
func main() {
err := func1()
fmt.Printf("func1 error: %v ", err)
}
上面的xt方式平时也会用到,通过 context 怎么实现呢?
下面来看下如何使用 context 进行主动取消、超时取消。
主动取消:
func func1(ctx context.Context, wg *sync.WaitGroup) error {
defer wg.Done()
respC := make(chan int)
go func() {
time.Sleep(time.Second * 5) // 模拟业务逻辑处理
respC }()
// 使 取消机制
select {
case <-ctx.Done():
fmt.Println("cancel")
return errors.New("cancel")
case r := <-respC:
fmt.Println(r)
return nil
}
}
func main() {
wg := &sync.WaitGroup{}
ctx, cancel := context.WithCancel(contex用场t.Background())
wg.Add(1)
go func1(ctx, wg)
time.Sleep(time.Second * 2)
cancel() // 主动取消
wg.Wait() // 等待 goroutine 退出
}
超时取消:
func func1(ctx context.Context) {
resp := make(chan int)
go func() {
time.Sleep(time.Second * 5) // 模拟处理逻细数辑
resp }()
// 超时机制
select {
case <-ctx.Done():
fmt.Println("ctx timeout")
fmt.Println(ctx.Err())
case <-resp:
fmt.Println("done")
}
return
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Se Ccond*2)
defer cancel()
func1(ctx)
}3.防止 goroutine 泄露。
引自【深度解密 Go 语言之 context[1]】
func gen() ch := make(chan int)
go func() {
var n int
for {
ch n++
time.Sleep(time.Second)
}
}()
return ch
}
这是一个可以生成无限整数的协程,但如果我只需要它产生的前 5 个数,那么就会发生 gorouontine 泄漏:
func main() {
for n := range gen() {
fmt.Println(n)
if n == 5 {
break
}
}
// ……
}
当 n == 5 的时候,直接 break 掉。那么 gen 函数的协程就会执行无限循环,永远不会停下来。发生了 goroutine 泄漏。
用 context 改进这个例子:
func gen(ctx context.Context) ch := make(chan int)
go func(te) {
var n int
for {
select {
case <-ctx.Done():
return
case ch n++
time.Sleep(time.Second)
}
}
}()
return ch
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // 避免其他地方忘记 cancel,且重xt复调用不影响
for n := range gen(ctx) {
fmt.Println(n)
if n == 5 {
cancel()
break
}
}
// ……
}
增加一个 context,在 break 前调用 cancel 函数,取消 goroutine。gen 函数在接收到取消信号后,直接退出,系统回收资源。
总结
这篇文章列出的几个例子是 context 最基本的使用场景,其他框架、第三包基本上都是从这几种用法扩展的,所以非常有必要掌握基 使础用法。
另外希望这篇文章能给你带来帮助,如果文中有理解错误之处或者你还想到其他用法,可以在留言区留言,一定回复!抱团学习不孤单!
参考资料
[1]深度解密Go语言之context: https://qcrao.com/2019/06/12/dive-into-go-context/
- ·Docker 发布开发团队 2021 年三个首选方向
- ·华纳兄弟探索公司起诉 Midjourney侵犯其版权角色
- ·标签: 追觅科技 俞浩 小红书 算法推荐
- ·标签: HuggingFace OpenAI 人工智能 大模型
- ·标签: 拼多多 美团 京东 饿了么
- ·如何基于K3s构建云原生边缘基础设施?
- ·农业智能化新突破!中国农业大学发布神农大模型3.0
- ·如何使用KMaaS应对多云密钥管理挑战
- ·标签: 蔡磊 渐冻症 京东 AI医疗
- ·老外大学生发明AI模型:可快速生成中国山水画 人眼难辨真假
- ·字节跳动公开关于云应用方面的新专利
- ·AI公司Motion 公司获 3800 万美元融资,助力中小企业的智能化转型
- ·传亚马逊正与意大利谈判 投资几十亿欧元扩大云计算规模
- ·Perplexity AI 将 Comet 浏览器扩展至印度 Pro 用户
- ·标签: 魔法原子 吴长征 陈春玉 人形机器人
- ·标签: 和铂医药 诺纳生物 免疫性疾病 肿瘤
- ·https://www.tombow.com/en/search/谷歌搜索留痕外推技术【tg:seogoogle987】,YlU
- ·https://www.wou.edu.my/?s=谷歌搜索留痕外推技术【tg:seogoogle987】,fzb
- ·https://www.lenovo.com/gb/en/search?action=SEARCH&text=谷歌搜索留痕外推技术【tg:seogoogle987】,Ljw
- ·https://www.mesec.cz/vyhledavani/?qs=谷歌搜索留痕外推技术【tg:seogoogle987】,Tqp
- ·https://www.kuaikanmanhua.com/sou/谷歌搜索留痕外推技术【tg:seogoogle987】,qfJ
- ·https://www.remit.co.jp/vi/?s=谷歌搜索留痕外推技术【tg:seogoogle987】nrs
- ·https://www.sonepar.ch/fr/search?q=谷歌搜索留痕外推技术【tg:seogoogle987】,06o
- ·https://yscc1986.net/search/谷歌搜索留痕外推技术【tg:seogoogle987】Wae
- ·https://www.lneg.pt/en/?s=谷歌搜索留痕外推技术【tg:seogoogle987】,Q6y
- ·https://www.parriscues.com/catalogsearch/result/?q=谷歌搜索留痕外推技术【tg:seogoogle987】,pEC
