2016-01-20 3 views
2

Я использую goroutines/channels. Вот мой код. Почему тайм-аут не выполняется?Тайм-аут Golang не выполняется с каналами

func main() { 
    c1 := make(chan int, 1) 

    go func() { 
     for { 
      time.Sleep(1500 * time.Millisecond) 
      c1 <- 10 
     } 
    }() 

    go func() { 
     for { 
      select { 
      case i := <-c1: 
       fmt.Println(i) 
      case <-time.After(2000 * time.Millisecond): 
       fmt.Println("TIMEOUT") // <-- Not Executed 
      } 
     } 
    }() 

    fmt.Scanln() 
} 

ответ

2

Ваш тайм-аут не произойдет, потому что один из вашего goroutine посылает значение на вашем c1 канала каждые 1,5 секунды (или около того) несколько раз, и ваш тайм-аут случится только тогда, когда нет никакого значения, которые будут получены от c1 в течение 2 секунд.

После того, как значение принимается от c1, в следующей итерации исполняющего select опять новыйtime.After() вызов будет сделан, который возвращающий новый канал, на котором значение будет отправлено только еще через 2 секунды. Канал тайм-аута из предыдущего исполнения select отбрасывается и больше не используется.

Чтобы получить тайм-аут после 2-х секунд, создать канал таймаута только один раз, например .:

timeout := time.After(2000 * time.Millisecond) 
for { 
    select { 
    case i := <-c1: 
     fmt.Println(i) 
    case <-timeout: 
     fmt.Println("TIMEOUT") // Will get executed after 2 sec 
    } 
} 

Выход:

10 
TIMEOUT 
10 
10 
10 
...