通道计时器,处理事件的新思路

简介: 通道计时器,处理事件的新思路

概述

在 Go 语言中,通道(Channel)和计时器(Timer)是两个强大的并发工具,它们的结合使用可以优雅地处理各种事件。

本文将探讨如何使用通道响应计时器的事件,并通过详实的示例代码展示在不同场景下的应用。


 

1. 通道与计时器基础

1.1 通道的基本概念

通道是 Go 语言中并发编程的核心机制之一,用于在不同的 goroutine 之间传递数据。

make 函数创建


ch := make(chan int)

1.2 计时器的基本概念

计时器是 Go 语言中用于定时执行任务的工具,通过 time 包提供。

创建一个计时器


timer := time.NewTimer(time.Second)


 

2. 使用通道接收计时器事件

2.

package main
import (  "fmt"  "time")
func main() {  ch := make(chan string)
  go func() {    time.Sleep(2 * time.Second)    ch <- "事件发生"  }()
  select {  case msg := <-ch:    fmt.Println(msg)  case <-time.After(3 * time.Second):    fmt.Println("超时,未接收到事件")  }}

在上面示例中,创建了一个通道 ch,并在一个新的 goroutine 中等待 2 秒后往通道发送消息。

select 语句监听通道的消息和计时器的事件,哪个先到达就执行哪个。

2.2 计时器复用


package main
import (  "fmt"  "time")
func main() {  ch := make(chan string)  timer := time.NewTimer(2 * time.Second)
  go func() {    time.Sleep(1 * time.Second)    ch <- "事件发生"  }()
  select {  case msg := <-ch:    fmt.Println(msg)  case <-timer.C:    fmt.Println("超时,未接收到事件")  }}

在上述示例中,创建了一个计时器 timer,它设置为 2 秒。

同样,用 select 监听通道和计时器的事件,但这次用 timer.C 直接监听计时器的事件。


 

3. 使用通道控制计时器

3.1 通道关闭触发计时器


package main
import (  "fmt"  "time")
func main() {  ch := make(chan string)  timer := time.NewTimer(3 * time.Second)
  go func() {    time.Sleep(2 * time.Second)    close(ch)  }()
  select {    case msg, ok := <-ch:    if !ok {      fmt.Println("通道已关闭")      break    }    fmt.Println(msg)    case <-timer.C:    fmt.Println("超时,未接收到事件")  }}

在上面示例中,在 goroutine 中等待 2 秒后关闭通道。

用检查 ok 的值,可以知道通道是否已关闭,从而避免读取已关闭通道引发的异常。

3.

package main
import (  "fmt"  "time")
func main() {  ch := make(chan string, 1)  timer := time.NewTimer(3 * time.Second)
  go func() {    time.Sleep(2 * time.Second)    ch <- "事件发生"  }()
  select {  case msg := <-ch:    fmt.Println(msg)  case <-timer.C:    fmt.Println("超时,未接收到事件")  }}

在这个示例中,将通道 ch 设置为带缓冲的通道,容量为 1。

这样,即使计时器事件先到,通道也能接收到消息,因为有缓冲空间。


 

4. 实战场景

4.1

package main
import (  "fmt"  "time")
func main() {  ticker := time.NewTicker(1 * time.Second)  defer ticker.Stop()
  for {    select {    case <-ticker.C:      fmt.Println("定时任务执行")    }  }}

在上述示例中,使用 time.NewTicker 创建了一个定时器,并通过 select 监听定时器的事件。

在每次定时器触发时,执行相应的周期性任务。

4

package main
import (  "fmt"  "time")
func main() {  ch := make(chan string)
  select {  case msg := <-ch:    fmt.Println(msg)    case <-time.After(3 * time.Second):    fmt.Println("超时,未接收到事件")  }}

在上面示例中,用 time.After 函数创建一个计时器,当超时时,会向通道发送当前时间。

select 监听通道和计时器的事件,实现超时处理。


 

5. 总结

通过本文的讲解和示例代码,了解了如何使用通道响应计时器的事件。

通道和计时器的结合使用能够优雅地处理各种并发场景,包括超时处理、周期性任务等。

当然,使用通道来响应计时器也有一些注意事项:

通道操作需要确保同步正确,避免数据竞争

需要确保不会漏掉计时器的事件

重置计时器时要小心计时和通道处理的时序关系

在使用 Go 语言的并发编程特性时,记住思考通道、同步和事件顺序,这会帮助你编写出高质量和正确的 Go 程序。

目录
相关文章
|
6月前
|
缓存 数据库
定时器的应用场景?
定时器的应用场景?
|
2月前
|
前端开发 JavaScript
前端基础(十三)_定时器(间歇定时器、延迟定时器)
本文介绍了JavaScript中定时器的使用,包括`setTimeout`和`setInterval`两种类型。`setTimeout`是实现延迟执行,即等待一定时间后执行一次指定的函数;而`setInterval`是实现间歇执行,即每隔一定时间就执行一次指定的函数。文章还介绍了如何使用`clearTimeout`和`clearInterval`来取消定时器的执行,并通过示例代码展示了定时器的创建和取消。
94 4
前端基础(十三)_定时器(间歇定时器、延迟定时器)
|
2月前
|
Linux C语言
epoll的水平和边缘触发机制技术分享
在Linux系统中,epoll是一种高效的I/O多路复用机制,用于监视多个文件描述符上的I/O事件。epoll提供了两种主要的工作模式:水平触发(Level Triggered, LT)和边缘触发(Edge Triggered, ET),它们各自在事件通知和处理机制上有所不同。下面将详细探讨这两种触发模式的技术细节和在实际工作学习中的应用。
70 1
|
C#
C# 中串口通信 serialport1.DataReceived 函数无法触发或者出发延时等等问题解决方法
原文:C# 中串口通信 serialport1.DataReceived 函数无法触发或者出发延时等等问题解决方法 以前这个问题困扰我多天最后查资料一大堆,最后最终攻克了,看到非常多人做C#串口都遇到相同的问题,所以写一篇博文,以便学习交流。
3434 0
|
6月前
基于若依的ruoyi-nbcio流程管理系统支持支持定时边界事件和定时捕获事件
基于若依的ruoyi-nbcio流程管理系统支持支持定时边界事件和定时捕获事件
85 2
|
6月前
|
监控 安全 持续交付
【专栏】Webhook是服务器主动发送事件通知的机制,打破传统客户端轮询模式,实现数据实时高效传递。
【4月更文挑战第29天】Webhook是服务器主动发送事件通知的机制,打破传统客户端轮询模式,实现数据实时高效传递。常用于持续集成部署、第三方服务集成、实时数据同步和监控告警。具有实时性、高效性和灵活性优势,但也面临安全风险和调试挑战。理解并善用Webhook能提升系统性能,广泛应用于现代软件开发和集成。
415 0
|
6月前
|
传感器 人工智能 算法
掌握C++中的状态-事件回调矩阵:打造强大的有限状态机
掌握C++中的状态-事件回调矩阵:打造强大的有限状态机
127 0
|
前端开发
Electron 渲染进程与渲染进程之间的实时通信 (实时触发及接收消息)
Electron 渲染进程与渲染进程之间的实时通信 (实时触发及接收消息)
[虚幻引擎插件介绍] DTGlobalEvent 蓝图全局事件, Actor, UMG 相互回调,自由回调通知事件函数,支持自定义参数。
本插件可以在虚幻的蓝图 Actor, Obiect,UMG 里面指定绑定和执行消息,可带自定义参数。 参数支持 Bool,Byte,Int,Int64,Float,Name,String,Text,Vector,Rotator,Transform,Object,Actor。
88 0
|
存储 缓存 监控
I/O多路复用中的水平触发和边缘触发
I/O多路复用中的水平触发和边缘触发
212 0