往建设厅网站上传东西,网络营销中网站的目的是,WordPress积分插件制作,快速免费建网站✨✨ 欢迎大家来到景天科技苑✨✨
#x1f388;#x1f388; 养成好习惯#xff0c;先赞后看哦~#x1f388;#x1f388; #x1f3c6; 作者简介#xff1a;景天科技苑 #x1f3c6;《头衔》#xff1a;大厂架构师#xff0c;华为云开发者社区专家博主#xff0c;…
✨✨ 欢迎大家来到景天科技苑✨✨ 养成好习惯先赞后看哦~ 作者简介景天科技苑 《头衔》大厂架构师华为云开发者社区专家博主阿里云开发者社区专家博主CSDN全栈领域优质创作者掘金优秀博主51CTO博客专家等。 《博客》Python全栈Golang开发PyQt5和Tkinter桌面开发小程序开发人工智能js逆向App逆向网络系统安全数据分析Djangofastapiflask等框架云原生K8Slinuxshell脚本等实操经验网站搭建数据库等分享。 所属的专栏Go语言开发零基础到高阶实战 景天的主页景天科技苑 文章目录 Go语言中的定时器一、Timer定时器1. 创建Timer2. 停止Timer3. 重置Timer4. time.AfterFunc5. time.After 二、Ticker定时器1. 创建Ticker2. 监听Ticker事件3. 停止Ticker定时器 三、定时器应用案例1. 定时打印日志2. 周期性检查系统状态 四、总结 Go语言中的定时器
在Go语言中定时器是并发编程中常用的工具之一。定时器可以用于监控某个goroutine的运行时间、定时打印日志、周期性执行任务等多种场景。 Go标准库提供了两种主要的定时器Timer一次性定时器和Ticker周期性定时器。本文将详细介绍这两种定时器的用法并通过实际案例展示其应用场景。
一、Timer定时器
Timer定时器是一种一次性定时器即在未来某个时刻触发的事件只会执行一次。 Timer的结构中包含一个Time类型的管道C主要用于事件通知。 在未到达设定时间时管道内没有数据写入一直处于阻塞状态到达设定时间后会向管道内写入一个系统时间触发事件。
1. 创建Timer
使用time.NewTimer函数可以创建一个Timer定时器。该函数接受一个Duration类型的参数表示定时器的超时时间并返回一个*Timer类型的指针。 看下源码Timer结构体中timer.C是一个时间类型的通道
package mainimport (fmttime
)func main() {// func NewTimer(d Duration) *Timertimer : time.NewTimer(2 * time.Second) // 设置超时时间2秒// 先打印下当前时间fmt.Println(当前时间:, time.Now())//我们可以打印下这个只读通道的值//timer.C就是我们在定义定时器的时候存放的时间等待对应的时间。现在这个就是根据当前时间加2秒fmt.Println(通道里面的值, -timer.C)
}可以看到timer.C这个只读通道里面的值就是通过NewTimer设置时间间隔后的时间
因此我们可以根据时间通道来定时将来某个时间要做的事
package mainimport (fmttime
)func main() {timer : time.NewTimer(2 * time.Second) // 设置超时时间2秒-timer.C//经过两秒后只想下面代码fmt.Println(after 2s Time out!)
}在上述代码中创建了一个超时时间为2秒的定时器程序会阻塞在-timer.C处直到2秒后定时器触发程序继续执行并打印“after 2s Time out!”。
2. 停止Timer
使用Stop方法可以停止一个Timer定时器。该方法返回一个布尔值表示定时器是否在超时前被停止。 如果返回true表示定时器在超时前被成功停止如果返回false表示定时器已经超时或已经被停止过。
package mainimport (fmttime
)func main() {timer : time.NewTimer(2 * time.Second) // 设置超时时间2秒//这里创建定时器后里面执行了停止方法肯定是在定时器超时前停止了返回trueres : timer.Stop()fmt.Println(res) // 输出true
}在上述代码中创建了一个超时时间为2秒的定时器并立即调用Stop方法停止它。由于定时器还没有超时所以Stop方法返回true。
3. 重置Timer
对于已经过期或者是已经停止的Timer可以通过Reset方法重新激活它并设置新的超时时间。Reset方法也返回一个布尔值表示定时器是否在重置前已经停止或过期。
package mainimport (fmttime
)func main() {timer : time.NewTimer(2 * time.Second)-timer.Cfmt.Println(time out1)//经过两秒后定时器超时了res1 : timer.Stop()//此时再stop得到的是falsefmt.Printf(res1 is %t\n, res1) // 输出false//然后我们重置定时器。重置成3秒后超时timer.Reset(3 * time.Second)res2 : timer.Stop()//此时再stop由于定时器没超时得到的是truefmt.Printf(res2 is %t\n, res2) // 输出true
}在上述代码中首先创建了一个超时时间为2秒的定时器并在超时后打印“time out1”。 然后调用Stop方法停止定时器由于定时器已经过期所以Stop方法返回false。 接着调用Reset方法将定时器重新激活并设置新的超时时间为3秒。 最后再次调用Stop方法停止定时器由于此时定时器还没有过期所以Stop方法返回true。
4. time.AfterFunc
time.AfterFunc函数可以接受一个Duration类型的参数和一个函数f返回一个*Timer类型的指针。在创建Timer之后等待一段时间d然后执行函数f。
package mainimport (fmttime
)func main() {duration : time.Duration(1) * time.Secondf : func() {fmt.Println(f has been called after 1s by time.AfterFunc)}// func AfterFunc(d Duration, f func()) *Timer//等待duration时间后执行f函数//这里是经过1秒后。执行f函数timer : time.AfterFunc(duration, f)defer timer.Stop()time.Sleep(2 * time.Second)
}在上述代码中创建了一个超时时间为1秒的定时器并在超时后执行函数f。 使用defer语句确保在程序结束时停止定时器。程序会在1秒后打印“f has been called after 1s by time.AfterFunc”。
5. time.After
time.After函数会返回一个*Timer类型的管道该管道会在经过指定时间段d后写入数据。调用这个函数相当于实现了一个定时器。
package mainimport (fmttime
)func main() {ch : make(chan string)go func() {time.Sleep(3 * time.Second)ch - test}()//使用select哪个先到来耗时时间短执行哪个select {case val : -ch:fmt.Printf(val is %s\n, val)// 这个case是两秒后执行// func After(d Duration) -chan Timecase -time.After(2 * time.Second):fmt.Println(timeout!!!)}
}在上述代码中创建了一个管道ch并在另一个goroutine中等待3秒后向管道写入数据。 在主goroutine中使用select语句监听两个管道一个是刚刚创建的ch另一个是time.After函数返回的管道c。 由于ch管道3秒后才会有数据写入而time.After函数是2秒超时所以2秒后select会先收到管道c里的数据执行“timeout!!!”并退出。
二、Ticker定时器
Ticker定时器可以周期性地不断触发时间事件不需要额外的Reset操作。Ticker的结构中也包含一个Time类型的管道C每隔固定时间段d就会向该管道发送当前的时间根据这个管道消息来触发事件。
Ticker定时器是Go标准库time包中的一个重要组件。它允许你每隔一定的时间间隔执行一次指定的操作。Ticker定时器在创建时会启动一个后台goroutine该goroutine会按照指定的时间间隔不断向一个通道Channel发送当前的时间值。
1. 创建Ticker
要创建一个Ticker定时器你可以使用time.NewTicker函数。这个函数接受一个time.Duration类型的参数表示时间间隔并返回一个*time.Ticker类型的指针。 Ticker定时器的核心是一个通道Channel你可以通过监听这个通道来接收时间间隔到达的事件。
ticker : time.NewTicker(1 * time.Second)上面的代码创建了一个每隔1秒触发一次的Ticker定时器。
2. 监听Ticker事件
要监听Ticker定时器的事件你可以使用range关键字或者select语句来监听Ticker定时器的通道。每次时间间隔到达时Ticker定时器的通道都会接收到一个当前的时间值。
for range ticker.C { // 在这里执行周期性任务
}package mainimport (fmttime
)func main() {ticker : time.NewTicker(1 * time.Second)//查看定时器数据类型fmt.Printf(定时器数据类型%T\n, ticker)//启动协程来监听定时器触发事件通过time.Sleep函数来等待5秒钟然后调用ticker.Stop()函数来停止定时器。//最后输出定时器停止表示定时器已经成功停止。go func() {for range ticker.C {fmt.Println(Ticker ticked)}}()//执行5秒后让定时器停止time.Sleep(5 * time.Second)ticker.Stop()fmt.Println(定时器停止)
}或者如果你需要同时监听多个通道你可以使用select语句
select {
case t : -ticker.C: // 处理Ticker定时器事件
case -stopChan: // 处理停止信号
}package mainimport (fmttime
)func main() {ticker : time.NewTicker(1 * time.Second) // 创建一个每秒触发一次的Ticker定时器defer ticker.Stop() // 确保在main函数结束时停止定时器for {select {case t : -ticker.C:fmt.Println(Tick at, t)}}
}每秒执行一次
3. 停止Ticker定时器
当你不再需要Ticker定时器时你应该调用它的Stop方法来停止它。停止Ticker定时器可以释放与之关联的资源并防止不必要的goroutine继续运行。 ticker.Stop()
停止Ticker定时器后它的通道将不再接收任何事件。
package mainimport (fmttime
)func main() {ticker : time.NewTicker(500 * time.Millisecond) // 创建一个每500毫秒触发一次的Ticker定时器timeEnd : make(chan bool) // 用于停止Ticker定时器的通道go func() {for {select {//当达到设置的停止条件式停止循环case -timeEnd:fmt.Println(结束任务)breakcase t : -ticker.C:fmt.Println(500毫秒响应一次:, t)}}}()time.Sleep(5 * time.Second) // 主线程等待5秒钟ticker.Stop() // 停止Ticker定时器timeEnd - true // 发送结束信号fmt.Println(定时任务结束)
}持续执行5秒后定时器停止运行
三、定时器应用案例
1. 定时打印日志
Ticker定时器的一个常见应用是定时打印日志。通过设置一个Ticker定时器你可以每隔固定的时间间隔输出一次日志信息从而监控程序的运行状态。
package mainimport (fmttime
)func main() {ticker : time.NewTicker(5 * time.Second)defer ticker.Stop() // 确保程序结束时停止Ticker定时器for range ticker.C {// 打印当前时间作为日志fmt.Println(Current time:, time.Now())}
}5秒打印一次
在这个例子中我们创建了一个每隔5秒触发一次的Ticker定时器并在一个无限循环中监听它的事件。 每次事件触发时我们都会打印当前的时间作为日志信息。注意由于我们在main函数中使用了defer语句来确保Ticker定时器在程序结束时被停止所以即使循环是无限的程序也不会因为Ticker定时器而泄漏资源。
然而在实际应用中你可能需要在某个条件下提前停止Ticker定时器。这时你可以使用一个额外的通道来发送停止信号
package mainimport (fmttime
)func main() {ticker : time.NewTicker(5 * time.Second)stopChan : make(chan struct{})go func() {// 模拟一个运行一段时间的任务time.Sleep(15 * time.Second)// 发送停止信号stopChan - struct{}{}}()for {select {case t : -ticker.C:fmt.Println(Tick at, t)case -stopChan:fmt.Println(Ticker stopped)ticker.Stop()return}}
}在这个例子中我们创建了一个额外的stopChan通道来发送停止信号。我们启动了一个goroutine来模拟一个运行一段时间的任务并在任务完成后向stopChan发送一个停止信号。 在for循环中我们使用select语句同时监听Ticker定时器的通道和stopChan通道。当接收到停止信号时我们停止Ticker定时器并退出程序。
2. 周期性检查系统状态
Ticker定时器还可以用于周期性检查系统状态。例如你可以每隔一段时间检查一次服务器的负载、内存使用情况或数据库连接数等关键指标并在发现异常时采取相应的措施。
package mainimport (fmtmath/randtime
)// 模拟检查系统状态的函数
func checkSystemStatus() {// 这里可以添加实际的检查逻辑// 例如检查CPU使用率、内存使用情况等// 这里我们随机生成一个0到100之间的数作为模拟结果status : rand.Intn(101)fmt.Printf(System status: %d\n, status)// 假设状态大于80表示系统异常if status 80 {fmt.Println(Warning: System status is above normal!)// 这里可以添加处理异常的逻辑// 例如发送警报、重启服务等}
}func main() {ticker : time.NewTicker(10 * time.Second)defer ticker.Stop() // 确保程序结束时停止Ticker定时器for range ticker.C {checkSystemStatus()}
}在这个例子中我们创建了一个每隔10秒触发一次的Ticker定时器并在一个无限循环中监听它的事件。 每次事件触发时我们都会调用checkSystemStatus函数来模拟检查系统状态。checkSystemStatus函数会随机生成一个0到100之间的数作为模拟结果并根据结果判断是否系统异常。 如果系统异常即状态大于80则打印警告信息并可以在这里添加处理异常的逻辑。
同样地你可以使用额外的通道来发送停止信号以便在需要时提前停止Ticker定时器。
四、总结
本文详细介绍了Go语言中Timer和Ticker两种定时器的用法并通过实际案例展示了它们的应用场景。Timer定时器适用于需要一次性触发的事件而Ticker定时器适用于需要周期性触发的事件希望在大家go的学习与应用上能够帮助到大家。