代码之家  ›  专栏  ›  技术社区  ›  Trần Kim Dá»±

Golang通道:超时模式不适用于示例

  •  0
  • Trần Kim Dá»±  · 技术社区  · 7 年前

    Timeout pattern 为了我的项目。以下是上述链接的示例代码:

    c1 := make(chan string, 1)
    go func() {
        time.Sleep(2 * time.Second)
        c1 <- "result 1"
    }()
    
    select {
    case res := <-c1:
        fmt.Println(res)
    case <-time.After(1 * time.Second):
        fmt.Println("timeout 1")
    }
    

    另一个例子是:

    c2 := make(chan string, 1)
        go func() {
            time.Sleep(2 * time.Second)
            c2 <- "result 2"
        }()
        select {
        case res := <-c2:
            fmt.Println(res)
        case <-time.After(3 * time.Second):
            fmt.Println("timeout 2")
        }
    

    for {
        select {
        case ev := <-c.EventChannel():
            // do something here
        case <-time.After(2 * time.Second):
            // this condition never happend
            return
        default:
           // do nothing as non-blocking channel pattern
        }
    }
    

    但我不知道为什么代码永远不会遇到超时情况。当我搬家的时候 time.After(2 * time.Second) 在单独的语句中,它是有效的。以下是修改后的代码:

    timeout := time.After(2 * time.Second)
    for {
        select {
        case ev := <-c.EventChannel():
            // do something here
        case <-timeout:
            require.Equal(t, "time out after 2s", "")
        default:
            // do nothing as non-blocking channel pattern
        }
    }
    

    1 回复  |  直到 7 年前
        1
  •  3
  •   Shettyh    7 年前

    基本上,如果有默认情况,select语句不会等待,因此在您的情况下,它只检查 EventChannel 并转到默认情况,因为它没有阻塞并且不会等待 2 seconds timeout 2 secs 超时,所以它永远不会被执行。

    在第二种情况下,由于计时器在循环之外,它不会在每次迭代之后重新初始化 2 seconds

    如果你想等待 2秒 在每次迭代中,您都可以这样做

    for {
      select {
      case ev := <-c.EventChannel():
          // do something here
      default:
          // do nothing as non-blocking channel pattern
      }
      time.Sleep(2 *time.Second)