我遇到一个**context**应用场景问题,有点疑惑,来向各位先进请教。
我在某个**Redis**操作函数中,要将一系列**Key**的值进行修改。伪代码如下:
```
// 创建一个2秒超时的context
ctx, cancel := context.WithTimeout(context.Background(), time.Second * 2)
defer cancel()
// 获取所有匹配的Keys(数量不定)
keys, err := redis.Keys(ctx, "device_*")
// ...
// 循环,更新Key的值
for _, key := range keys {
newValue := getNewValue(key)
// 疑惑是下面这几句,假设循环可能有几千或上万次,
// 那么下面用到的context(也是设置2秒超时),是每次都创建一个新的?还是另有它法?
ctx, cancel := context.WithTimeout(context.Background(), time.Second * 2)
defer cancel()
_, err = redis.Set(ctx, key, newValue )
// ...
}
```
你这里没必要使用context.WithTimeout,在进入方法后直接声明一个context.TODO()或者context.Background()的变量,然后在每次调用中使用这个变量就可以了
context.WithTimeout和context.WithDeadline(),真正使用的时候还需要一个监听超时的动作,
```go
select {
case <-ctx.Done():
return ctx.Err()
case out <- v:
}
```
如果超时了,就丢弃子协程的操作结果(虽然有cancel方法,事实上并不会真的取消子协程的运行)
参考context.go源码Done() <-chan struct{}的注释
#1
更多评论