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

细数 Context 使用场景

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

标签:
  • 热门焦点
  • 一加Ace2 Pro真机揭晓 钛空灰配色质感拉满

    终于,在经过了几波预热之后,一加Ace2 Pro的外观真机图在网上出现了。还是博主数码闲聊站曝光的,这次的外观设计还是延续了一加11的方案,只是细节上有了调整,例如新加入了钛空灰
  • 小米平板5 Pro 12.4简评:多专多能 兼顾影音娱乐的大屏利器

    疫情带来了网课,网课盘活了安卓平板,安卓平板市场虽然中途停滞了几年,但好的一点就是停滞的这几年行业又有了新的发展方向,例如超窄边框、高刷新率、多摄镜头组合等,这就让安卓
  • 7月安卓手机性价比榜:努比亚+红魔两款新机入榜

    7月登场的新机有努比亚Z50S Pro和红魔8S Pro,除了三星之外目前唯二的两款搭载超频版骁龙8Gen2处理器的产品,而且努比亚和红魔也一贯有着不错的性价比,所以在本次的性价比榜单
  • 5月安卓手机好评榜:魅族20 Pro夺冠

    性能榜和性价比榜之后,我们来看最后的安卓手机好评榜,数据来源安兔兔评测,收集时间2023年5月1日至5月31日,仅限国内市场。第一名:魅族20 Pro好评率:97.50%不得不感慨魅族老品牌还
  • 一加首款折叠屏!一加Open渲染图出炉:罕见单手可握小尺寸

    8月5日消息,此前就有爆料称,一加首款折叠屏手机将会在第三季度上市,如今随着时间临近,新机的各种消息也开始浮出水面。据悉,这款新机将会被命名为&ldquo;On
  • 摸鱼心法第一章——和配置文件说拜拜

    为了能摸鱼我们团队做了容器化,但是带来的问题是服务配置文件很麻烦,然后大家在群里进行了“亲切友好”的沟通图片图片图片图片对比就对比,简单对比下独立配置中心和k8s作为配
  • 企业采用CRM系统的11个好处

    客户关系管理(CRM)软件可以为企业提供很多的好处,从客户保留到提高生产力。  CRM软件用于企业收集客户互动,以改善客户体验和满意度。  CRM软件市场规模如今超过580
  • 三分钟白话RocketMQ系列—— 如何发送消息

    我们知道RocketMQ主要分为消息 生产、存储(消息堆积)、消费 三大块领域。那接下来,我们白话一下,RocketMQ是如何发送消息的,揭秘消息生产全过程。注意,如果白话中不小心提到相关代
  • 2022爆款:ROG魔霸6 冰川散热系统持续护航

    喜逢开学季,各大商家开始推出自己的新产品,进行打折促销活动。对于忠实的端游爱好者来说,能够拥有一款梦寐以求的笔记本电脑是一件十分开心的事。但是现在的
Top