Golang 计时器

151 阅读1分钟

Golang想实现计时器的功能,一般有三种 第一种是for循环中不断sleep,但是更多地,我们使用Go提供的两个结构来实现。

timer.Timer

type Timer struct {
    C <-chan Time
    r runtimeTimer
}
type runtimeTimer struct {
    tb uintptr
    i  int

    when   int64
    period int64
    f      func(interface{}, uintptr) // NOTE: must not be closure
    arg    interface{}
    seq    uintptr
}

可以看出,Timer结构有一个只读的channel,还有一个runtimeTimer类型的结构体

使用定时器Timer一般都是通过NewTimerAfterFunc函数来获取

func NewTimer(d *Duration) *Timer {
	c := make(chan Time, 1)
	t := &Timer {
		C: c,
		r: runtimeTimer {
			when: when(d), //表示经过d时间,调用f
			f: sendTime, // f表示一个函数调用,sendTime表示向Timer.C发送当前的时间
			arg: c, // arg表示调用f时传递的参数, c用于接受接受sendTime发送时间
		}
	}
	startTimer(&t.r)
	return t
}

例子

package main  
  
import (  
	"fmt"  
	"time"  
)  
  
func Love() {  
	timer := time.NewTimer(2 * time.Second) 
	// 新建一个Timer 
	for {  
		select {  
			case <-timer.C:  
			fmt.Println("I Love You!")  
			timer.Reset(2 * time.Second)  
			// 上一个when执行完成,重置时间
		}  
	}  
	return  
}  
func main() {  
	go Love()  
	stop := 0  
	for {  
		fmt.Scan(&stop)  
		if stop == 1 {  
			break  
		}  
	}  
}

time.Tricker

TrickerTimer的结构是类似的,Tricker是一个重复版本的Timer,它会在重复的时间d后向Tricker中写入数据。(即不需要time.Reset()方法)

func main() {
	tricker := time.NewTricker(time.Millisecond * 500)
	go func() {
		for t := range tricker.C {
			fmt.Println(t)
			fmt.Println("I Love You!")
		}
	}()

	time.Sleep(time.Second * 10)
	tricker.Stop()
}