Golang 通道:超时模式不起作用作为示例
Golang channel: timeout pattern not work as example
我尝试为我的项目实施 Timeout pattern。这是上面的示例代码 link:
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
}
}
我不知道2个案例之间的区别。以及为什么第一个例子有效。请帮我想想办法。
谢谢
基本上,如果存在默认情况,select 语句不会等待,因此在您的情况下,它只检查 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)
}
我尝试为我的项目实施 Timeout pattern。这是上面的示例代码 link:
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
}
}
我不知道2个案例之间的区别。以及为什么第一个例子有效。请帮我想想办法。
谢谢
基本上,如果存在默认情况,select 语句不会等待,因此在您的情况下,它只检查 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)
}