杰克工作室 发表于 2023-4-1 20:41

golang中time.After一直无法跳出select循环

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

<pre>
package main

import (
        &quot;fmt&quot;
        &quot;math/rand&quot;
        &quot;time&quot;
)

func main() {
        ch := make(chan int)

        go func() {
                for v := range ch {
                        fmt.Println(v)
                }
        }()
END:
        for {
                select {
                case ch &lt;- rand.Int():
                case &lt;-time.After(time.Second * 3):
                        fmt.Println(&quot;timeout&quot;)
                        break END
                }
                time.Sleep(time.Second)
        }
}
</pre>

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

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

<p>time.After 方法的源码如下:</p>

<pre>
func After(d Duration) &lt;-chan Time {
        return NewTimer(d).C
}
</pre>

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

<pre>
func NewTimer(d Duration) *Timer {
        c := make(chan Time, 1)
        t := &amp;Timer{
                C: c,
                r: runtimeTimer{
                        when: when(d),
                        f:    sendTime,
                        arg:c,
                },
        }
        startTimer(&amp;t.r)
        return t
}
</pre>

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

<pre>
package main

import (
        &quot;fmt&quot;
        &quot;math/rand&quot;
        &quot;time&quot;
)

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 &lt;- rand.Int():
                case &lt;-timer:
                        fmt.Println(&quot;timeout&quot;)
                        break END
                }
                time.Sleep(time.Second)
        }
}</pre>

<p>源文地址:https://www.cnblogs.com/jkko123/p/12733487.html</p>
页: [1]
查看完整版本: golang中time.After一直无法跳出select循环