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

细数 Context 使用场景

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

标签:
  • 热门焦点
  • Find N3入网:最高支持16+1TB

    OPPO将于近期登场的Find N3折叠屏目前已经正式入网,型号为PHN110。本次Find N3在外观方面相比前两代有很大的变化,不再是小号的横向折叠屏,而是跟别的厂商一样采用了较为常见的
  • vivo TWS Air开箱体验:真轻 臻好听

    在vivo S15系列新机的发布会上,vivo的最新款真无线蓝牙耳机vivo TWS Air也一同发布,本次就这款耳机新品给大家带来一个简单的分享。外包装盒上,vivo TWS Air保持了vivo自家产
  • 7月安卓手机性价比榜:努比亚+红魔两款新机入榜

    7月登场的新机有努比亚Z50S Pro和红魔8S Pro,除了三星之外目前唯二的两款搭载超频版骁龙8Gen2处理器的产品,而且努比亚和红魔也一贯有着不错的性价比,所以在本次的性价比榜单
  • 5月iOS设备性能榜:M1 M2依旧是榜单前五

    和上个月一样,没有新品发布的iOS设备性能榜的上榜设备并没有什么更替,仅仅只有跑分变化而产生的排名变动,刚刚开始的苹果WWDC2023,推出的产品也依旧是新款Mac Pro、新款Mac Stu
  • 六大权益!华为8月服务日开启:手机免费贴膜、维修免人工费

    8月5日消息,一年一度的华为开发者大会2023(Together)日前在松山湖拉开帷幕,与此同时,华为8月服务日也式开启,到店可享六大专属权益。华为用户可在华为商城Ap
  • 共享单车的故事讲到哪了?

    来源丨海克财经与共享充电宝相差不多,共享单车已很久没有被国内热点新闻关照到了。除了一再涨价和用户直呼用不起了。近日多家媒体再发报道称,成都、天津、郑州等地多个共享单
  • 重估百度丨大模型,能撑起百度的“今天”吗?

    自象限原创 作者|程心 罗辑2023年之前,对于自己的&ldquo;今天&rdquo;,百度也很迷茫。&ldquo;新业务到 2022 年底还是 0,希望 2023 年出来一个 1。&rdquo;这是2022年底,李彦宏
  • iQOO Neo8 Pro即将开售:到手价3099元起 安卓性能最强旗舰

    5月23日,iQOO如期举行了新品发布会,全新的iQOO Neo8系列也正式与大家见面,包含iQOO Neo8和iQOO Neo8 Pro两个版本,其中标准版搭载高通骁龙8+,而Pro版更
  • 微软发布Windows 11新版 引入全新任务栏状态

    近日,微软发布了Windows 11新版,而Build 22563更新主要引入了几周前曝光的平板模式任务栏等,系统更流畅了。更新中,Windows 11加入了专门针对平板优化的任务栏
Top