Golang中计时器的工作原理

huangapple go评论74阅读模式
英文:

How timers work in Golang

问题

我正在尝试理解Go语言中的通道。这是一个简单的代码示例:

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	var wg sync.WaitGroup
	wg.Add(1)

	go func() {
		defer wg.Done()

		i := 0

		for {
			select {
			case <-time.After(3 * time.Second):
				fmt.Println("EXIT: 3 seconds")
				return
			case <-time.After(1 * time.Second):
				fmt.Println(i, "second")
			}
			i++
		}
	}()

	wg.Wait()
}

我期望控制台输出结果如下:

0 second
1 second
2 second
EXIT: 3 seconds

但实际上输出结果是这样的:

0 second
1 second
2 second
3 second
4 second
5 second
6 second
...

我错过了什么关于这个计时器的问题,我该如何解决这个问题?

英文:

I'm trying to undersand channels in Go. There is a simple code

package main

import (
    &quot;fmt&quot;
    &quot;sync&quot;
    &quot;time&quot;
)

func main() {
    var wg sync.WaitGroup
    wg.Add(1)

    go func() {
	    defer wg.Done()

	    i := 0

	    for {
		    select {
		    case &lt;-time.After(3 * time.Second):
			    fmt.Println(&quot;EXIT: 3 seconds&quot;)
			    return
		    case &lt;-time.After(1 * time.Second):
			    fmt.Println(i, &quot;second&quot;)
		}
		i++
	}
}()

wg.Wait()
}

I expect console result like this

0 second
1 second
2 second
EXIT: 3 seconds

But actually it is like this

0 second
1 second
2 second
3 second
4 second
5 second
6 second
...

What am I missing with this timer and how can I fix a problem?

答案1

得分: 3

这是因为使用了for循环。循环中的每一次迭代,select语句中的case <-time.After(3 * time.Second)会被重新评估并生成一个新的计时器。例如,按照以下方式进行操作,事情应该能够正常工作:

stop := time.After(3 * time.Second)
for {
    select {
        case <-stop:
            fmt.Println("退出:3秒")
            return
        case <-time.After(1 * time.Second):
            fmt.Println(i, "秒")
    }
}
英文:

It's because of for loop. Each circle of loop RightHandSide of case &lt;-time.After(3 * time.Second): in select statement evaluated and give you fresh timer. For example this way things should work

stop := time.After(3 * time.Second)
for {
	select {
		case &lt;-stop:
			fmt.Println(&quot;EXIT: 3 seconds&quot;)
			return
		case &lt;-time.After(1 * time.Second):
			fmt.Println(i, &quot;second&quot;)
	}
}

huangapple
  • 本文由 发表于 2017年1月25日 19:35:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/41850612.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定