首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在go中重用带有context.WithTimeout的父上下文?

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

Stack Overflow用户
提问于 2020-04-17 18:21:00
回答 1查看 1.9K关注 0票数 4

通过新的超时对context.WithTimeout重用父上下文

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

基本原理

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

问题

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

documentation 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()?这意味着父上下文将不会被传递。:(

代码语言:javascript
复制
// 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
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-17 18:30:26

它看起来像是对context.WithTimeout的第一次调用,隐藏了父上下文ctx。后面的进程重用了这个已经取消的上下文,因此出现了错误。您必须重用父对象。下面是更新后的示例:

代码语言:javascript
复制
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)
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61269264

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档