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

细数 Context 使用场景

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

标签:
  • 热门焦点
  • Redmi Buds 4开箱简评:才199还有降噪 可以无脑入

    在上个月举办的Redmi Note11T Pro系列新机发布会上,除了两款手机新品之外,Redmi还带来了两款TWS真无线蓝牙耳机产品,Redmi Buds 4和Redmi Buds 4 Pro,此前我们在Redmi Note11T
  • 7月安卓手机性能榜:红魔8S Pro再夺榜首

    7月份的手机市场风平浪静,除了红魔和努比亚带来了两款搭载骁龙8Gen2领先版处理器的新机之外,别的也想不到有什么新品了,这也正常,通常6月7月都是手机厂商修整的时间,进入8月份之
  • 0糖0卡0脂 旭日森林仙草乌龙茶优惠:15瓶到手29元

    旭日森林无糖仙草乌龙茶510ml*15瓶平时要卖为79.9元,今日下单领取50元优惠券,到手价为29.9元。产品规格:0糖0卡0脂,添加草本仙草汁,清凉爽口,富含茶多酚,保留
  • 三言两语说透设计模式的艺术-简单工厂模式

    一、写在前面工厂模式是最常见的一种创建型设计模式,通常说的工厂模式指的是工厂方法模式,是使用频率最高的工厂模式。简单工厂模式又称为静态工厂方法模式,不属于GoF 23种设计
  • 十个可以手动编写的 JavaScript 数组 API

    JavaScript 中有很多API,使用得当,会很方便,省力不少。 你知道它的原理吗? 今天这篇文章,我们将对它们进行一次小总结。现在开始吧。1.forEach()forEach()用于遍历数组接收一参
  • 电视息屏休眠仍有网络上传 爱奇艺被质疑“薅消费者羊毛”

    记者丨宁晓敏 见习生丨汗青出品丨鳌头财经(theSankei) 前不久,爱奇艺发布了一份亮眼的一季报,不仅营收和会员营收创造历史最佳表现,其运营利润也连续6个月实现增长。自去年年初
  • “又被陈思诚骗了”

    作者|张思齐 出品|众面(ID:ZhongMian_ZM)如今的国产悬疑电影,成了陈思诚的天下。最近大爆电影《消失的她》票房突破30亿断层夺魁暑期档,陈思诚再度风头无两。你可以说陈思诚的
  • SN570 NVMe SSD固态硬盘 价格与性能兼具

    SN570 NVMe SSD固态硬盘是西部数据发布的最新一代WD Blue系列的固态硬盘,不仅闪存技术更为精进,性能也得到了进一步的跃升。WD Blue SN570 NVMe SSD的包装外
  • AI艺术欣赏体验会在上海梅赛德斯奔驰中心音乐俱乐部上演

    光影交错的镜像世界,虚实幻化的视觉奇观,虚拟偶像与真人共同主持,这些场景都出现在2019世界人工智能大会的舞台上。8月29日至31日,“AI艺术欣赏体验会”在上海
Top