想写个延时执行功能,第一步我是打开baidu

NewTimer倒计时计时器使用总结

使用案例

time.NewTimer() 是 Go 语言标准库 time 包中的一个函数,用于创建一个新的定时器(Timer)。

我们首先通过一个简单的例子,来展示计时器的使用。在这个例子中,我们将创建一个定时器。

package main

import (
	"fmt"
	"time"
)

func main() {
	// 创建一个定时器,设置为2秒后触发
	timer := time.NewTimer(2 * time.Second)
	fmt.Println("开始执行")
	// 阻塞等待定时器到期
	<-timer.C
	fmt.Println("定时器到期")
}

我们再举一个稍微复杂一点的例子,假设有一个需求,要求在 5 秒钟内完成某个任务,否则就认为任务失败。这时我们就可以使用 NewTimer 来实现超时控制。

package main

import (
	"fmt"
	"time"
)

func main() {
	//创建一个定时器,超时时间为5 秒钟
	timer := time.NewTimer(5 * time.Second)
	done := make(chan bool, 1)
	//启动一个goroutine执行任务,并在任务完成后向通道发送一个完成信号
	go func() {
		//模拟任务执行耗时
		time.Sleep(6 * time.Second)
		done <- true
	}()
	
	select {
	case <-done:
		//任务完成,输出完成信息
		fmt.Println("Task finished. ")
	case <-timer.C:
		//超时,输出超时信息
		fmt.Println("Task timed out. ")
	}
}

从timer.C取出的是当时的系统时间。

原理分析

分析time.NewTimer()

// 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
}

// 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
}

Timer.r是runtimeTimer结构体类型,这个名称带了runtime,大概率是和运行时包有关。

// Interface to timers implemented in package runtime.
// Must be in sync with ../runtime/time.go:/^type timer
type runtimeTimer struct {
	pp       uintptr
	when     int64
	period   int64
	f        func(any, uintptr) // NOTE: must not be closure
	arg      any
	seq      uintptr
	nextwhen int64
	status   uint32
}

从这个结构体的注释来看确实是在runtime包里面实现的。

下面来看看startTimer(&t.r)这个函数。

func startTimer(*runtimeTimer)

然后再点不进去。我们去runtime/time.go寻找可以发现如下代码。

// startTimer adds t to the timer heap.
//
//go:linkname startTimer time.startTimer
func startTimer(t *timer) {
	if raceenabled {
		racerelease(unsafe.Pointer(t))
	}
	addtimer(t)
}

它的作用是启动一个定时器,当定时器到期时,会执行相应的回调函数,即r.f,f这里传入的是sendTime回调函数。

// sendTime does a non-blocking send of the current time on c.
func sendTime(c any, seq uintptr) {
	select {
	case c.(chan Time) <- Now():
	default:
	}
}

startTimer 函数内部,会使用系统调用来启动一个底层的操作系统定时器,等到定时器超时时,底层系统会自动触发一个信号(例如 Unix 平台上的 SIGALRM 信号),然后该信号将由 Go 运行时内部的信号处理函数捕获,并最终调用相关的回调函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shulu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值