使用上下文重用父上下文。带新超时的WithTimeout
嗨,我是go
的新手。我想知道是否可以重用父上下文来创建多个上下文。withTimeout((。原理是我必须按顺序调用多个网络请求,并希望使用父上下文同时为每个请求设置超时。
基本原理
当父对象的上下文被取消时,所有请求也将被取消。
问题
在下面的代码中,它显示了一个示例,其中LongProcess
是网络请求。然而,在可以用context deadline exceeded
进行第二个LongProcess
调用之前,上下文是关闭的。
文件withDeadline
说明The returned context's Done channel is closed when the deadline expires, when the returned cancel function is called, or when the parent context's Done channel isclosed, whichever happens first.
如果是这样的话,有没有办法重置withTimeout的计时器?还是必须为每个请求创建一个新的上下文context.Background()
?这意味着父上下文将不会被传递(
// LongProcess refers to a long network request
func LongProcess(ctx context.Context, duration time.Duration, msg string) error {
c1 := make(chan string, 1)
go func() {
// Simulate processing
time.Sleep(duration)
c1 <- msg
}()
select {
case m := <-c1:
fmt.Println(m)
return nil
case <-ctx.Done():
return ctx.Err()
}
}
func main() {
ctx := context.Background()
t := 2 * time.Second
ctx, cancel := context.WithTimeout(ctx, t)
defer cancel()
// Simulate a 2 second process time
err := LongProcess(ctx, 2*time.Second, "first process")
fmt.Println(err)
// Reusing the context.
s, cancel := context.WithTimeout(ctx, t)
defer cancel()
// Simulate a 1 second process time
err = LongProcess(s, 1*time.Second, "second process")
fmt.Println(err) // context deadline exceeded
}
它看起来像是对context.WithTimeout
的第一个调用遮蔽了父上下文ctx
。后面的过程重用了这个已经取消的上下文,因此出现了错误。您必须重复使用父对象。以下是更新的示例:
func main() {
// Avoid to shadow child contexts
parent := context.Background()
t := 2 * time.Second
// Use the parent context.
ctx1, cancel := context.WithTimeout(parent, t)
defer cancel()
err := LongProcess(ctx1, 2*time.Second, "first process")
fmt.Println(err)
// Use the parent context not the canceled one.
ctx2, cancel := context.WithTimeout(parent, t)
defer cancel()
err = LongProcess(ctx2, 1*time.Second, "second process")
fmt.Println(err)
}