为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
紫衣仙女 2022-08-01 18:59:16
我想用来处理我发出外部请求的用例,如果请求的响应太长,它将返回错误。context.WithTimeout()我已经实现了伪代码,如下面附带的 playground 链接:2 解决方案:主->未预料到预计main_1 ->package mainimport (    "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
查看完整描述

2 回答

?
HUX布斯

TA贡献1876条经验 获得超6个赞

最好在函数中处理上下文,这样就可以将其用作 中的同步函数。makeHTTPRequest()main()


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


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

    ch := make(chan string)


    go func() {

        time.Sleep(10 * time.Second)

        select {

        case ch <- "abc":

        default:

            // When context deadline exceeded, there is no receiver

            // This case will prevent goroutine blocking forever

            return

        }

    }()


    select {

    case <-ctx.Done():

        return "", ctx.Err()

    case result := <-ch:

        return result, nil

    }

}


func main() {

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

    defer cancel()


    fmt.Printf("[%v] Begin make request \n", time.Now())

    abc, err := makeHTTPRequest(ctx)

    if err != nil {

        fmt.Printf("[%v] Return error: %v \n", time.Now(), err)

        return

    }

    fmt.Printf("[%v] %s", time.Now(), abc)

}


查看完整回答
反对 回复 2022-08-01
?
慕标5832272

TA贡献1966条经验 获得超4个赞

如果我没看错的话。有两个问题。

  1. 你想知道为什么main()函数不起作用吗?

  2. 最佳实践是什么?

第 1 季度

main()在 makeHTTPRequest 中被阻止,在此期间,上下文有超时。因此,不能按预期工作。

第 2 季度

个例子可以回答你。在 中,您的代码已经是最佳做法。main_1()


查看完整回答
反对 回复 2022-08-01
  • 2 回答
  • 0 关注
  • 167 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号