当前位置:首页 > 科技  > 知识百科

细数 Context 使用场景

来源: 责编: 时间:2023-08-07 16:29:55 359观看
导读 你好,我是四哥。前一篇文章从源码的角度详细介绍了 Context 的实现原理,但是还没有提到 Context 的使用场景,今天我们一起来看下:1.请求链路传值。传值使用方式如下:func func1(c

你好,我是四哥。mdI28资讯网——每日最新资讯28at.com

前一篇文章从源码的角度详细介绍了 Context 的实现原理,但是还没有提到 Context 的使用场景,今天我们一起来看下:mdI28资讯网——每日最新资讯28at.com

1.请求链路传值。mdI28资讯网——每日最新资讯28at.com

传值使用方式如下:mdI28资讯网——每日最新资讯28at.com

func func1(ctx context.Context) {mdI28资讯网——每日最新资讯28at.com
ctx = context.WithValue(ctx, "k1", "v1")mdI28资讯网——每日最新资讯28at.com
func2(ctx)mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
mdI28资讯网——每日最新资讯28at.com
func func2(ctx context.Context) {mdI28资讯网——每日最新资讯28at.com
fmt.Println("func2:",ctx.Value("k1").(string))mdI28资讯网——每日最新资讯28at.com
ctx = context.WithValue(ctx, "k2", "v2")mdI28资讯网——每日最新资讯28at.com
func3(ctx)mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
mdI28资讯网——每日最新资讯28at.com
func func3(ctx context.Context) {mdI28资讯网——每日最新资讯28at.com
fmt.Println("func3:",ctx.Value("k1").(string))mdI28资讯网——每日最新资讯28at.com
fmt.Println("func3:",ctx.Value("k2").(string))mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
mdI28资讯网——每日最新资讯28at.com
func main() {mdI28资讯网——每日最新资讯28at.com
ctx := context.Background()mdI28资讯网——每日最新资讯28at.com
func1(ctx)mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com

我们在 func1() 通过函数 WithValue() 设置了一个键值对 k1-v1,在 func2() 可以获取到 func1() 设置的键值对,如果调用 func3() 时把这个 ctx 继续传入的话,在 func3() 中依然还是可以获取到 k1-v1。mdI28资讯网——每日最新资讯28at.com

但是在 func1() 中获取不到 func2() 设置的键值对 k2-v2,因为 context 只能自上而下携带值,这点需要注意。mdI28资讯网——每日最新资讯28at.com

2.取消耗时操作,及时释放资源。mdI28资讯网——每日最新资讯28at.com

使用 channel + select 的机制:mdI28资讯网——每日最新资讯28at.com

func func1() error {mdI28资讯网——每日最新资讯28at.com
respC := make(chan int) // 起消息通知作用mdI28资讯网——每日最新资讯28at.com
// 处理逻辑mdI28资讯网——每日最新资讯28at.com
go func() {mdI28资讯网——每日最新资讯28at.com
time.Sleep(time.Second * 3) // 模拟处理业务逻辑mdI28资讯网——每日最新资讯28at.com
respC close(respC)mdI28资讯网——每日最新资讯28at.com
}()mdI28资讯网——每日最新资讯28at.com
mdI28资讯网——每日最新资讯28at.com
// 判断是否超时mdI28资讯网——每日最新资讯28at.com
select {mdI28资讯网——每日最新资讯28at.com
case r := <-respC:mdI28资讯网——每日最新资讯28at.com
fmt.Printf("Resp: %d ", r)mdI28资讯网——每日最新资讯28at.com
return nilmdI28资讯网——每日最新资讯28at.com
case <-time.After(time.Second * 2): // 超过设置的时间就报错mdI28资讯网——每日最新资讯28at.com
fmt.Println("catch timeout")mdI28资讯网——每日最新资讯28at.com
return errors.New("timeout")mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
mdI28资讯网——每日最新资讯28at.com
func main() {mdI28资讯网——每日最新资讯28at.com
err := func1()mdI28资讯网——每日最新资讯28at.com
fmt.Printf("func1 error: %v ", err)mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com

上面的方式平时也会用到,通过 context 怎么实现呢?mdI28资讯网——每日最新资讯28at.com

下面来看下如何使用 context 进行主动取消、超时取消。mdI28资讯网——每日最新资讯28at.com

主动取消:mdI28资讯网——每日最新资讯28at.com

func func1(ctx context.Context, wg *sync.WaitGroup) error {mdI28资讯网——每日最新资讯28at.com
defer wg.Done()mdI28资讯网——每日最新资讯28at.com
respC := make(chan int)mdI28资讯网——每日最新资讯28at.com
go func() {mdI28资讯网——每日最新资讯28at.com
time.Sleep(time.Second * 5) // 模拟业务逻辑处理mdI28资讯网——每日最新资讯28at.com
respC }()mdI28资讯网——每日最新资讯28at.com
// 取消机制mdI28资讯网——每日最新资讯28at.com
select {mdI28资讯网——每日最新资讯28at.com
case <-ctx.Done():mdI28资讯网——每日最新资讯28at.com
fmt.Println("cancel")mdI28资讯网——每日最新资讯28at.com
return errors.New("cancel")mdI28资讯网——每日最新资讯28at.com
case r := <-respC:mdI28资讯网——每日最新资讯28at.com
fmt.Println(r)mdI28资讯网——每日最新资讯28at.com
return nilmdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
mdI28资讯网——每日最新资讯28at.com
func main() {mdI28资讯网——每日最新资讯28at.com
wg := &sync.WaitGroup{}mdI28资讯网——每日最新资讯28at.com
ctx, cancel := context.WithCancel(context.Background())mdI28资讯网——每日最新资讯28at.com
wg.Add(1)mdI28资讯网——每日最新资讯28at.com
go func1(ctx, wg)mdI28资讯网——每日最新资讯28at.com
time.Sleep(time.Second * 2)mdI28资讯网——每日最新资讯28at.com
cancel() // 主动取消mdI28资讯网——每日最新资讯28at.com
wg.Wait() // 等待 goroutine 退出mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com

超时取消:mdI28资讯网——每日最新资讯28at.com

func func1(ctx context.Context) {mdI28资讯网——每日最新资讯28at.com
resp := make(chan int)mdI28资讯网——每日最新资讯28at.com
go func() {mdI28资讯网——每日最新资讯28at.com
time.Sleep(time.Second * 5) // 模拟处理逻辑mdI28资讯网——每日最新资讯28at.com
resp }()mdI28资讯网——每日最新资讯28at.com
// 超时机制mdI28资讯网——每日最新资讯28at.com
select {mdI28资讯网——每日最新资讯28at.com
case <-ctx.Done():mdI28资讯网——每日最新资讯28at.com
fmt.Println("ctx timeout")mdI28资讯网——每日最新资讯28at.com
fmt.Println(ctx.Err())mdI28资讯网——每日最新资讯28at.com
case <-resp:mdI28资讯网——每日最新资讯28at.com
fmt.Println("done")mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
returnmdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
func main() {mdI28资讯网——每日最新资讯28at.com
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)mdI28资讯网——每日最新资讯28at.com
defer cancel()mdI28资讯网——每日最新资讯28at.com
func1(ctx)mdI28资讯网——每日最新资讯28at.com
}3.防止 goroutine 泄露。mdI28资讯网——每日最新资讯28at.com

引自【深度解密 Go 语言之 context[1]】mdI28资讯网——每日最新资讯28at.com

func gen() ch := make(chan int)mdI28资讯网——每日最新资讯28at.com
go func() {mdI28资讯网——每日最新资讯28at.com
var n intmdI28资讯网——每日最新资讯28at.com
for {mdI28资讯网——每日最新资讯28at.com
ch n++mdI28资讯网——每日最新资讯28at.com
time.Sleep(time.Second)mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
}()mdI28资讯网——每日最新资讯28at.com
return chmdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com

这是一个可以生成无限整数的协程,但如果我只需要它产生的前 5 个数,那么就会发生 goroutine 泄漏:mdI28资讯网——每日最新资讯28at.com

func main() {mdI28资讯网——每日最新资讯28at.com
for n := range gen() {mdI28资讯网——每日最新资讯28at.com
fmt.Println(n)mdI28资讯网——每日最新资讯28at.com
if n == 5 {mdI28资讯网——每日最新资讯28at.com
breakmdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
// ……mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com

当 n == 5 的时候,直接 break 掉。那么 gen 函数的协程就会执行无限循环,永远不会停下来。发生了 goroutine 泄漏。mdI28资讯网——每日最新资讯28at.com

用 context 改进这个例子:mdI28资讯网——每日最新资讯28at.com

func gen(ctx context.Context) ch := make(chan int)mdI28资讯网——每日最新资讯28at.com
go func() {mdI28资讯网——每日最新资讯28at.com
var n intmdI28资讯网——每日最新资讯28at.com
for {mdI28资讯网——每日最新资讯28at.com
select {mdI28资讯网——每日最新资讯28at.com
case <-ctx.Done():mdI28资讯网——每日最新资讯28at.com
returnmdI28资讯网——每日最新资讯28at.com
case ch n++mdI28资讯网——每日最新资讯28at.com
time.Sleep(time.Second)mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
}()mdI28资讯网——每日最新资讯28at.com
return chmdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
mdI28资讯网——每日最新资讯28at.com
func main() {mdI28资讯网——每日最新资讯28at.com
ctx, cancel := context.WithCancel(context.Background())mdI28资讯网——每日最新资讯28at.com
defer cancel() // 避免其他地方忘记 cancel,且重复调用不影响mdI28资讯网——每日最新资讯28at.com
mdI28资讯网——每日最新资讯28at.com
for n := range gen(ctx) {mdI28资讯网——每日最新资讯28at.com
fmt.Println(n)mdI28资讯网——每日最新资讯28at.com
if n == 5 {mdI28资讯网——每日最新资讯28at.com
cancel()mdI28资讯网——每日最新资讯28at.com
breakmdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com
// ……mdI28资讯网——每日最新资讯28at.com
}mdI28资讯网——每日最新资讯28at.com

增加一个 context,在 break 前调用 cancel 函数,取消 goroutine。gen 函数在接收到取消信号后,直接退出,系统回收资源。mdI28资讯网——每日最新资讯28at.com

总结mdI28资讯网——每日最新资讯28at.com

这篇文章列出的几个例子是 context 最基本的使用场景,其他框架、第三包基本上都是从这几种用法扩展的,所以非常有必要掌握基础用法。mdI28资讯网——每日最新资讯28at.com

另外希望这篇文章能给你带来帮助,如果文中有理解错误之处或者你还想到其他用法,可以在留言区留言,一定回复!抱团学习不孤单!mdI28资讯网——每日最新资讯28at.com

参考资料mdI28资讯网——每日最新资讯28at.com

[1]深度解密Go语言之context: https://qcrao.com/2019/06/12/dive-into-go-context/mdI28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-119-2167-0.html细数 Context 使用场景

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 云计算开发:Python3-isdecimal()方法详解

下一篇: 数据分析八大模型:漏斗模型

标签:
  • 热门焦点
  • 2023年Q2用户偏好榜:12+256G版本成新主流

    3月份的性能榜、性价比榜和好评榜之后,就要轮到2023年的第二季度偏好榜了,上半年的新机潮已经过去,最明显的肯定就是大内存和存储的机型了,另外部分中端机也取消了屏幕塑料支架
  • 0糖0卡0脂 旭日森林仙草乌龙茶优惠:15瓶到手29元

    旭日森林无糖仙草乌龙茶510ml*15瓶平时要卖为79.9元,今日下单领取50元优惠券,到手价为29.9元。产品规格:0糖0卡0脂,添加草本仙草汁,清凉爽口,富含茶多酚,保留
  • JavaScript 混淆及反混淆代码工具

    介绍在我们开始学习反混淆之前,我们首先要了解一下代码混淆。如果不了解代码是如何混淆的,我们可能无法成功对代码进行反混淆,尤其是使用自定义混淆器对其进行混淆时。什么是混
  • 分布式系统中的CAP理论,面试必问,你理解了嘛?

    对于刚刚接触分布式系统的小伙伴们来说,一提起分布式系统,就感觉高大上,深不可测。而且看了很多书和视频还是一脸懵逼。这篇文章主要使用大白话的方式,带你理解一下分布式系统
  • 如何正确使用:Has和:Nth-Last-Child

    我们可以用CSS检查,以了解一组元素的数量是否小于或等于一个数字。例如,一个拥有三个或更多子项的grid。你可能会想,为什么需要这样做呢?在某些情况下,一个组件或一个布局可能会
  • 分享六款相见恨晚的PPT模版网站, 祝你做出精美的PPT!

    1、OfficePLUSOfficePLUS网站旨在为全球Office用户提供丰富的高品质原创PPT模板、实用文档、数据图表及个性化定制服务。优点:OfficePLUS是微软官方网站,囊括PPT模板、Word模
  • 19个 JavaScript 单行代码技巧,让你看起来像个专业人士

    今天这篇文章跟大家分享18个JS单行代码,你只需花几分钟时间,即可帮助您了解一些您可能不知道的 JS 知识,如果您已经知道了,就当作复习一下,古人云,温故而知新嘛。现在,我们就开始今
  • 中国家电海外掘金正当时|出海专题

    作者|吴南南编辑|胡展嘉运营|陈佳慧出品|零态LT(ID:LingTai_LT)2023年,出海市场战况空前,中国创业者在海外纷纷摩拳擦掌,以期能够把中国的商业模式、创业理念、战略打法输出海外,他们依
  • 三星Galaxy Z Fold5官方渲染图曝光:13.4mm折叠厚度依旧感人

    据官方此前宣布,三星将于7月26日在韩国首尔举办Unpacked活动,届时将带来带来包括Galaxy Buds 3、Galaxy Watch 6、Galaxy Tab S9、Galaxy Z Flip 5、
Top