英文:
Golang timeout is not executed with channels
问题
我正在使用goroutines/channels。以下是你的代码:
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()
}
为什么超时的情况没有被执行?
英文:
I am using goroutines/channels.
Here is my code.
Why is the timeout case not getting executed?
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()
}
答案1
得分: 4
你的超时不会发生,因为你的一个goroutine会在每1.5秒(左右)重复地向c1
通道发送一个值,只有当c1
中没有要接收的值时,超时才会发生。
一旦从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") // 2秒后执行
}
}
输出:
10
TIMEOUT
10
10
10
...
英文:
Your timeout doesn't happen, because one of your goroutine sends a value on your c1
channel in every 1.5 seconds (or so) repeatedly, and your timeout would only happen if there is no value to be received from c1
for 2 seconds.
Once a value is received from c1
, in the next iteration executing select
again a new time.After()
call will be made which which returns a new channel on which a value will only be sent after another 2 seconds. The timeout channel from the previous select
execution is discarded and is not used anymore.
To receive the timeout after 2 seconds, create the timeout channel only once, e.g.:
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
}
}
Output:
10
TIMEOUT
10
10
10
...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论