与上下文一起使用时的最佳做法是什么?WithTimeout() in Go?

我想用来处理我发出外部请求的用例,如果请求的响应太长,它将返回错误。context.WithTimeout()

我已经实现了伪代码,如下面附带的 playground 链接:2 解决方案:

  • 主->未预料到

  • 预计main_1 ->

package main


import (

    "context"

    "fmt"

    "time"

)


// I just dummy sleep in this func to produce use case this func

// need 10s to process and handle logic. 

// And this assume will be out of timeOut expect (5s)

func makeHTTPRequest(ctx context.Context) (string, error) {

    time.Sleep(time.Duration(10) * time.Second)

    return "abc", nil

}


// In main Func, I will set timeout is 5 second. 

func main() {

    var strCh = make(chan string, 1)

    ctx, cancel := context.WithTimeout(context.Background(), time.Duration(5)*time.Second)

    defer cancel()


    fmt.Print("Begin make request\n")

    abc, err := makeHTTPRequest(ctx)

    if err != nil {

        fmt.Print("Return error\n")

        return

    }


    select {

    case <-ctx.Done():

        fmt.Printf("Return ctx error: %s\n", ctx.Err())

        return

    case strCh <- abc:

        fmt.Print("Return response\n")

        return

    }

}


func main_1() {

    var strCh = make(chan string, 1)

    var errCh = make(chan error, 1)

    ctx, cancel := context.WithTimeout(context.Background(), time.Duration(5)*time.Second)

    defer cancel()


    go func() {

        fmt.Print("Begin make request\n")

        abc, err := makeHTTPRequest(ctx)

        if err != nil {

            fmt.Print("Return error\n")

            errCh <- err

            return

        }

        strCh <- abc


    }()

    select {

    case err := <-errCh:

        fmt.Printf("Return error: %s\n", err.Error())

        return

    case <-ctx.Done():

        fmt.Printf("Return ctx error: %s\n", ctx.Err())

        return

    case str := <-strCh:

        fmt.Printf("Return response: %s\n", str)

        return

    }

}

但是,如果使用该函数,则它无法按预期工作。但是,如果使用goroutine进行第二种实现,那么也许新的实现可以按预期工作。main()main_1()context.WithTimeout()


你能帮我回答这个问题吗?


https://play.golang.org/p/kZdlm_Tvljy


紫衣仙女
浏览 168回答 2
2回答

HUX布斯

最好在函数中处理上下文,这样就可以将其用作 中的同步函数。makeHTTPRequest()main()https://play.golang.org/p/Bhl4qprIBgHfunc makeHTTPRequest(ctx context.Context) (string, error) {&nbsp; &nbsp; ch := make(chan string)&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(10 * time.Second)&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case ch <- "abc":&nbsp; &nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // When context deadline exceeded, there is no receiver&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // This case will prevent goroutine blocking forever&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }()&nbsp; &nbsp; select {&nbsp; &nbsp; case <-ctx.Done():&nbsp; &nbsp; &nbsp; &nbsp; return "", ctx.Err()&nbsp; &nbsp; case result := <-ch:&nbsp; &nbsp; &nbsp; &nbsp; return result, nil&nbsp; &nbsp; }}func main() {&nbsp; &nbsp; ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)&nbsp; &nbsp; defer cancel()&nbsp; &nbsp; fmt.Printf("[%v] Begin make request \n", time.Now())&nbsp; &nbsp; abc, err := makeHTTPRequest(ctx)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("[%v] Return error: %v \n", time.Now(), err)&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Printf("[%v] %s", time.Now(), abc)}

慕标5832272

如果我没看错的话。有两个问题。你想知道为什么main()函数不起作用吗?最佳实践是什么?第 1 季度main()在 makeHTTPRequest 中被阻止,在此期间,上下文有超时。因此,不能按预期工作。第 2 季度这个例子可以回答你。在 中,您的代码已经是最佳做法。main_1()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go