
一、前言
我们在业务编程中常常会使用 context.WithTimeout 来对超时时间进行控制,来保障处理时效是在所控制的范围内,但对于Go原生的 context.WithTimeout 使用中存在一些限制,比如:超时时间只能改短不能改长或重置。
如果遇到在逻辑过程中使用goruntine来处理一个异步流程,context.WithTimeout应为接口超时设定了3秒,异步处理时间过长导致超时,想要给异步流程指定独立的timeout chatGPT给出的方法是通过 context.Background() 重新创建一个ctx。
但是这里会存在一个问题,就是context中的value会全部丢掉,比如里面存放的trace或者一些值将无法使用,把这个问题在给 chatGPT,它让通过WithValue挨个重新赋值…
本章就带给大家带来 chatGPT 也不知道的知识点,如何可以方便的重置 WithTimeout 又不丢失 value。

二、成熟的工具库"解君愁"
笔者一开始也不知道如何处理会比较好,感觉是一个通性问题就去问了下go-zero作者 万老师 ,给出了再go-zero中已经封装好的一个解法 contextx.ValueOnlyFrom
https://github.com/zeromicro/go-zero/blob/master/core/contextx/valueonlycontext.go
我们一起看下单测例子:
func Test_ValueOnlyFrom(t *testing.T) {
ctx := context.Background()
deadline, ok := ctx.Deadline()
assert.Equal(t, ok, false) // 没有截止日期
// 设置timeout
ctx, cancel := context.WithTimeout(ctx, time.Second*3)
defer cancel()
deadline, ok = ctx.Deadline()
assert.Equal(t, ok, true) // 有截止日期
assert.Equal(t, deadline.Unix(), time.Now().Unix()+3) // 日期为当前时间 + 3秒
// 超时时间改短(生效)
ctx, cancel = context.WithTimeout(ctx, time.Second*1)
defer cancel()
deadline, ok = ctx.Deadline()
assert.Equal(t, ok, true) // 有截止日期
assert.Equal(t, deadline.Unix(), time.Now().Unix()+1) // 日期为当前时间 + 1秒
// 超时时间改长(不生效)
ctx, cancel = context.WithTimeout(ctx, time.Second*5)
defer cancel()
deadline, ok = ctx.Deadline()
assert.Equal(t, ok, true) // 有截止日期
assert.Equal(t, deadline.Unix(), time.Now().Unix()+1) // 日期为当前时间 + 1秒
// 重置超时时间
ctx = contextx.ValueOnlyFrom(ctx)
deadline, ok = ctx.Deadline()
assert.Equal(t, ok, false) // 没有截止日期
// 超时时间改长(生效)
ctx, cancel = context.WithTimeout(ctx, time.Second*5)
defer cancel()
deadline, ok = ctx.Deadline()
assert.Equal(t, ok, true) // 有截止日期
assert.Equal(t, deadline.Unix(), time.Now().Unix()+5) // 日期为当前时间 + 5秒
}
三、源码理解
其实原理挺简单测,context就是一个 type Context interface ,只需要将其中和WithTimeout有关的几个方法进行改写就可以了,通过 valueOnlyContext 结构体继承 context.Context 就继承了 Value 值,仅改写Deadline、Done和Err 就能达到重置 WithTimeout 的效果, 而不改写 Value 方法对应的值也就保留下来了。


文章介绍了在Go编程中,如何解决使用context.WithTimeout设定超时时间后,无法延长或重置超时时间的问题。通过go-zero库中的contextx.ValueOnlyFrom方法,可以在不丢失values的情况下重置超时时间。文中提供了一个测试示例,展示如何使用这个工具函数,并解释了其工作原理,涉及context的Deadline、Done和Err方法的改写。
1705

被折叠的 条评论
为什么被折叠?



