Go-Timer

Time

首先有必要了解下go中Time的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type Time struct {
// sec gives the number of seconds elapsed since
// January 1, year 1 00:00:00 UTC.
sec int64
// nsec specifies a non-negative nanosecond
// offset within the second named by Seconds.
// It must be in the range [0, 999999999].
nsec int32
// loc specifies the Location that should be used to
// determine the minute, hour, month, day, and year
// that correspond to this Time.
// The nil location means UTC.
// All UTC times are represented with loc==nil, never loc==&utcLoc.
loc *Location
}

可以看到go语言中对于时间的定义:基于元年一月一日零点零分开始计算,精确到纳秒级别,至于底层是否能真正精确到这个级别就不得而知了。
还有一个重要的概念是Location,我在本地测试时区是CST,即大中华标准时间.
同时,go还提供了很多方便的辅助函数。
比较函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// After reports whether the time instant t is after u.
func (t Time) After(u Time) bool {
return t.sec > u.sec || t.sec == u.sec && t.nsec > u.nsec
}

// Before reports whether the time instant t is before u.
func (t Time) Before(u Time) bool {
return t.sec < u.sec || t.sec == u.sec && t.nsec < u.nsec
}

// Equal reports whether t and u represent the same time instant.
// Two times can be equal even if they are in different locations.
// For example, 6:00 +0200 CEST and 4:00 UTC are Equal.
// Do not use == with Time values.
func (t Time) Equal(u Time) bool {
return t.sec == u.sec && t.nsec == u.nsec
}

加减运算:

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
29
30
31
func (t Time) Add(d Duration) Time {
t.sec += int64(d / 1e9)
nsec := t.nsec + int32(d%1e9)
if nsec >= 1e9 {
t.sec++
nsec -= 1e9
} else if nsec < 0 {
t.sec--
nsec += 1e9
}
t.nsec = nsec
return t
}

func (t Time) Sub(u Time) Duration {
d := Duration(t.sec-u.sec)*Second + Duration(t.nsec-u.nsec)
// Check for overflow or underflow.
switch {
case u.Add(d).Equal(t):
return d // d is correct
case t.Before(u):
return minDuration // t - u is negative out of range
default:
return maxDuration // t - u is positive out of range
}

func (t Time) AddDate(years int, months int, days int) Time {
year, month, day := t.Date()
hour, min, sec := t.Clock()
return Date(year+years, month+Month(months), day+days, hour, min, sec, int(t.nsec), t.Location())
}

Timer

看下定时器的定义:

1
2
3
4
5
6
7
8
// The Timer type represents a single event.
// When the Timer expires, the current time will be sent on C,
// unless the Timer was created by AfterFunc.
// A Timer must be created with NewTimer or AfterFunc.
type Timer struct {
C <-chan Time
r runtimeTimer
}

根据文档内容,定时器是一个单独的事件,除非调用AfterFunc,当超时时,C会接收到当前时间。定时器只能通过NewTimer或者AfterFunc创建。
启动定时器,和停止定时器:

1
2
func startTimer( * runtimeTimer)
func stopTimer( * runtimeTimer) bool

NewTimer 和 AfterFunc

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
// NewTimer creates a new Timer that will send
// the current time on its channel after at least duration d.
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
}

func AfterFunc(d Duration, f func()) * Timer {
t := &Timer{
r: runtimeTimer{
when: when(d),
f: goFunc,
arg: f,
},
}
startTimer(&t.r)
return t
}

NewTimer初始化一个定时器,当超时之后会调用sendTime函数发送当前时间;AfterFunc接受一个func作为参数,当时间到了之后,执行func。

重设定时器

1
2
3
4
5
6
7
8
9
10
func (t * Timer) Reset(d Duration) bool {
if t.r.f == nil {
panic("time: Reset called on uninitialized Timer")
}
w := when(d)
active := stopTimer(&t.r)
t.r.when = w
startTimer(&t.r)
return active
}

After函数

1
2
3
4
5
6
7
8
9
// After waits for the duration to elapse and then sends the current time
// on the returned channel.
// It is equivalent to NewTimer(d).C.
// The underlying Timer is not recovered by the garbage collector
// until the timer fires. If efficiency is a concern, use NewTimer
// instead and call Timer.Stop if the timer is no longer needed.
func After(d Duration) <-chan Time {
return NewTimer(d).C
}

释放定时器资源

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
// Stop prevents the Timer from firing.
// It returns true if the call stops the timer, false if the timer has already
// expired or been stopped.
// Stop does not close the channel, to prevent a read from the channel succeeding
// incorrectly.
//
// To prevent a timer created with NewTimer from firing after a call to Stop,
// check the return value and drain the channel.
// For example, assuming the program has not received from t.C already:
// if !t.Stop() {
// <-t.C
// }
// This cannot be done concurrent to other receives from the Timer's
// channel.
//
// For a timer created with AfterFunc(d, f), if t.Stop returns false, then the timer
// has already expired and the function f has been started in its own goroutine;
// Stop does not wait for f to complete before returning.
// If the caller needs to know whether f is completed, it must coordinate
// with f explicitly.
func (t * Timer) Stop() bool {
if t.r.f == nil {
panic("time: Stop called on uninitialized Timer")
}
return stopTimer(&t.r)
}