posts - 404,  comments - 115,  views - 118万
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

问题的代码如下,在for select 循环中,本想通过 time.After 设置超时时间,但一直无法退出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main
 
import (
    "fmt"
    "math/rand"
    "time"
)
 
func main() {
    ch := make(chan int)
 
    go func() {
        for v := range ch {
            fmt.Println(v)
        }
    }()
END:
    for {
        select {
        case ch <- rand.Int():
        case <-time.After(time.Second * 3):
            fmt.Println("timeout")
            break END
        }
        time.Sleep(time.Second)
    }
}

控制台始终打印出从通道 ch 中读取的随机数,time.After 一直没能等到。

原因是每次进入到 case <-time.After(time.Second * 3): 时,都会创建一个新的通道返回,所以这个 case 每次都在等待接收新的通道的数据,永远不可能等到。

time.After 方法的源码如下:

1
2
3
func After(d Duration) <-chan Time {
    return NewTimer(d).C
}

每次调用都会通过 NewTimer 创建一个新的 Timer,并且 Timer.C 也是新创建的通道。

1
2
3
4
5
6
7
8
9
10
11
12
13
func NewTimer(d Duration) *Timer {
    c := make(chan Time, 1)
    t := &Timer{
        C: c,
        r: runtimeTimer{
            when: when(d),
            f:    sendTime,
            arg:  c,
        },
    }
    startTimer(&t.r)
    return t
}

为了解决上面的问题,我们可以把 time.After 放在 for 循环外面,来解决此问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main
 
import (
    "fmt"
    "math/rand"
    "time"
)
 
func main() {
    ch := make(chan int)
    timer := time.After(time.Second * 3)
 
    go func() {
        for v := range ch {
            fmt.Println(v)
        }
    }()
END:
    for {
        select {
        case ch <- rand.Int():
        case <-timer:
            fmt.Println("timeout")
            break END
        }
        time.Sleep(time.Second)
    }
}

 

posted on   怀素真  阅读(1253)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
点击右上角即可分享
微信分享提示