在 go 中重用带有 context.WithTimeout 的父上下文?

使用带有新超时的 context.WithTimeout 重用父上下文

你好,我是新来的go。我想知道是否可以重用父上下文来创建多个 context.withTimeout()。基本原理是我必须按顺序调用多个网络请求,并希望使用父上下文同时为每个请求设置超时。


基本原理

当父上下文被取消时,所有发出的请求也将被取消。


问题

在下面的代码中,它显示了一个示例,LongProcess即网络请求。LongProcess但是,在可以使用 进行第二次调用之前,上下文已关闭context deadline exceeded。


该文件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

}


慕桂英4014372
浏览 100回答 1
1回答

慕哥6287543

它看起来像是第一次调用context.WithTimeout隐藏父上下文ctx。后面的过程会重新使用这个已经取消的上下文,因此会出现错误。您必须重新使用父级。这是更新的示例:func main() {&nbsp; &nbsp; // Avoid to shadow child contexts&nbsp; &nbsp; parent := context.Background()&nbsp; &nbsp; t := 2 * time.Second&nbsp; &nbsp; // Use the parent context.&nbsp; &nbsp; ctx1, cancel := context.WithTimeout(parent, t)&nbsp; &nbsp; defer cancel()&nbsp; &nbsp; err := LongProcess(ctx1, 2*time.Second, "first process")&nbsp; &nbsp; fmt.Println(err)&nbsp; &nbsp; // Use the parent context not the canceled one.&nbsp; &nbsp; ctx2, cancel := context.WithTimeout(parent, t)&nbsp; &nbsp; defer cancel()&nbsp; &nbsp; err = LongProcess(ctx2, 1*time.Second, "second process")&nbsp; &nbsp; fmt.Println(err)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go