问题的代码如下,在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) } } |
版权声明:博主文章,可以不经博主允许随意转载,随意修改,知识是用来传播的。
分类:
golang
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 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 重磅开源!
· 字符编码:从基础到乱码解决