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

选择块如何等待 ctx.Done() 操作?

选择块如何等待 ctx.Done() 操作?

Go
繁星淼淼 2022-06-13 10:54:01
在下面的代码中:    ctx, cancel := context.WithTimeout(req.Context(), 5000*time.Second)    // Wait for the response or timeout    select {    case <-ctx.Done():        log.Println("timeout, cancel work...")        // Cancel the request and wait for it to complete        // this will shutdown the go-routine immediately        tr.CancelRequest(req)        log.Println(<-ch)    case err := <-ch:        // do something    }select同时等待两个接收操作。一个接收操作(<-ch)是一个块操作在块的执行中select,是否ctx.Done()在块中多次调用select以验证是否ctx.Done()返回通道?直到<-ch被封锁...
查看完整描述

2 回答

?
翻过高山走不出你

TA贡献1875条经验 获得超3个赞

规范:选择语句:

对于语句中的所有情况,在输入“select”语句时,接收操作的通道操作数以及发送语句的通道和右侧表达式仅按源顺序计算一次

select只调用ctx.Done()一次。它返回一个通道,并监视来自该通道的接收操作是否可以继续。

如果超时过期,5000*time.Second或者父上下文req.Context()(不再)。规格:接收运算符:cancel()ctx.Done()

关闭通道上的接收操作总是可以立即进行,在接收到任何先前发送的值之后产生元素类型的零值。


查看完整回答
反对 回复 2022-06-13
?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

通常,当你使用阻塞通道和超时功能时,你可以把它放在一个 for-select 循环中。


ctx, cancel := context.WithTimeout(req.Context(), 5000*time.Second)


    // Wait for the response or timeout

   for {

    select {

    case <-ctx.Done():

        log.Println("timeout, cancel work...")


        // Cancel the request and wait for it to complete

        // this will shutdown the go-routine immediately

        tr.CancelRequest(req)

        log.Println(<-ch)

        break

    case err := <-ch:

        // do something

        break

    }

   }

在这种情况下,<-ch不再阻塞,并且 select 调用ctx.Done()不止一次。如果您不使用 for 循环,ctx.Done()则只调用一次(正如@icza 已经指出的那样)


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

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信