kevinyan815 / gocookbook

go cook book

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

重置Timer的正确姿势

kevinyan815 opened this issue · comments

关于计时器的使用和重置计时器可能遇到的问题,可以看这篇文章:

Go语言计时器的使用详解

下面是使用Reset重置计时器的正确用法(防止drain channel操作阻塞线程)。

package main

import (
	"fmt"
	"time"
)

func main() {
	c := make(chan bool)

	go func() {
		for i := 0; i < 5; i++ {
			time.Sleep(time.Second * 6)
			c <- false
		}

		time.Sleep(time.Second * 6)
		c <- true
	}()

	go func() {
		// try to read from channel, block at most 5s.
		// if timeout, print time event and go on loop.
		// if read a message which is not the type we want(we want true, not false),
		// retry to read.
		timer := time.NewTimer(time.Second * 5)
		for {
			// timer is active , not fired, stop always returns true, no problems occurs.
			if !timer.Stop() {
				select {
				case <-timer.C:
				default:
				}

			}
			timer.Reset(time.Second * 5)
			select {
			case b := <-c:
				if b == false {
					fmt.Println(time.Now(), ":recv false. continue")
					continue
				}
				//we want true, not false
				fmt.Println(time.Now(), ":recv true. return")
				return
			case <-timer.C:
				fmt.Println(time.Now(), ":timer expired")
				continue
			}
		}
	}()

	//to avoid that all goroutine blocks.
	var s string
	fmt.Scanln(&s)
}