Канал Голанга: шаблон тайм-аута не работает как пример - PullRequest
0 голосов
/ 27 января 2019

Я пытаюсь реализовать Шаблон времени ожидания для моего проекта.Вот пример кода по вышеуказанной ссылке:

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 Ответ

0 голосов
/ 27 января 2019

В основном, оператор выбора не будет ждать, если есть регистр по умолчанию, поэтому в вашем случае он просто проверяет EventChannel и переходит к регистру по умолчанию, потому что он не блокирует, и он не будет ждать 2 seconds timeout. В каждой итерации есть 2 secs тайм-аут, поэтому он никогда не выполняется.

Во втором случае, поскольку таймер находится за пределами цикла, он не будет повторно инициализироваться в каждой итерации, поэтому после 2 seconds оператор select перехватит этот сигнал и выполнит тайм-аут.

Если вы хотите ждать 2 secs в каждой итерации, вы можете сделать что-то вроде этого

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

}

...