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

细数 Context 使用场景

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

标签:
  • 热门焦点
  • 谷歌KDD'23工作:如何提升推荐系统Ranking模型训练稳定性

    谷歌在KDD 2023发表了一篇工作,探索了推荐系统ranking模型的训练稳定性问题,分析了造成训练稳定性存在问题的潜在原因,以及现有的一些提升模型稳定性方法的不足,并提出了一种新
  • 多线程开发带来的问题与解决方法

    使用多线程主要会带来以下几个问题:(一)线程安全问题  线程安全问题指的是在某一线程从开始访问到结束访问某一数据期间,该数据被其他的线程所修改,那么对于当前线程而言,该线程
  • 一文搞定Java NIO,以及各种奇葩流

    大家好,我是哪吒。很多朋友问我,如何才能学好IO流,对各种流的概念,云里雾里的,不求甚解。用到的时候,现百度,功能虽然实现了,但是为什么用这个?不知道。更别说效率问题了~下次再遇到,
  • 共享单车的故事讲到哪了?

    来源丨海克财经与共享充电宝相差不多,共享单车已很久没有被国内热点新闻关照到了。除了一再涨价和用户直呼用不起了。近日多家媒体再发报道称,成都、天津、郑州等地多个共享单
  • 当家的盒马,加速谋生

    来源 | 价值星球Planet作者 | 归去来自己&ldquo;当家&rdquo;的盒马,开始加速谋生了。据盒马官微消息,盒马计划今年开放生鲜供应链,将其生鲜商品送往食堂。目前,盒马在上海已经与
  • 阿里大调整

    来源:产品刘有媒体报道称,近期淘宝天猫集团启动了近年来最大的人力制度改革,涉及员工绩效、层级体系等多个核心事项,目前已形成一个初步的&ldquo;征求意见版&rdquo;:1、取消P序列
  • 小米MIX Fold 3下月亮相:今年唯一无短板的全能折叠屏

    这段时间以来,包括三星、一加、荣耀等等有不少品牌旗下的最新折叠屏旗舰都有新的进展,其中荣耀、三星都已陆续发布了最新的折叠屏旗舰,尤其号荣耀Magi
  • 四年持续更迭坚持探索行业无人之境,HarmonyOS 4带来五大升级多项创新

    除了华为每年新发布的旗舰手机系列,上亿花粉更加期待鸿蒙系统每次的跨版本大更新。8月4日,HarmonyOS 4于HDC 2023正式发布,这也是该系统历经四年的再
  • 华为Mate60系列模具曝光:采用硕大圆形后置相机模组+拼接配色方案

    据此前多方爆料,今年华为将开始恢复一年双旗舰战略,除上半年推出的P60系列外,往年下半年的Mate系列也将迎来更新,有望在9-10月份带来全新的华为Mate60
Top