go里面关于超时的设计

设想一下你在接收源源不断的数据,如果有700ms没有收到,则认为是一个超时,需要做出处理。

逻辑上可以设计一个grouting,里面放一个通道,每收到一条数据进行相应处理。通道中夹杂一个timer定时器的处理,若通道在700ms内有数据,则定时器被重置,重新等待700ms再调用定时器处理函数,否则,700ms时间到,运行定时器处理函数。示例代码如下:

Go 复制代码
​
package main

import (
	"fmt"
	"runtime/debug"
	"strings"
	"time"
)

type demoSaveSuite struct {
	chanDemoSave chan string
}

const dbSaveWaitDuration = 700 * time.Millisecond

func (s *demoSaveSuite) DemoHandler() {
	go func() {
		defer func() {
			if r := recover(); r != nil {
				fmt.Println(string(debug.Stack()))
			}
		}()
		var timer *time.Timer
		for sqlEntity := range s.chanDemoSave {
			fmt.Printf("Received SQL entity: %s\n", sqlEntity)
			// 检查 sqlEntity 是否包含 "SQL_Entity_5"
			if strings.Contains(sqlEntity, "SQL_Entity_5") {
				if timer != nil {
					timer.Stop()
					timer = nil // 将 timer 设为 nil 以确保不再使用它
					continue    // 跳过本次循环的后续部分
				}
			}

			if timer == nil {
				timer = time.AfterFunc(dbSaveWaitDuration, func() {
					fmt.Printf("Executing action after delay for entity: %s\n", sqlEntity)
				})
			} else {
				timer.Reset(dbSaveWaitDuration)
			}
		}
	}()
}

func main() {
	// You can place your main code here if needed
	suite := &demoSaveSuite{
		chanDemoSave: make(chan string, 5), // Buffer to avoid blocking when sending messages
	}

	go suite.DemoHandler()

	// Send the first SQL entity
	suite.chanDemoSave <- "SQL_Entity_1_300Millisecond"
	time.Sleep(300 * time.Millisecond) // sleep a bit, but not enough for dbSaveWaitDuration

	// Send the second SQL entity
	suite.chanDemoSave <- "SQL_Entity_2_800Millisecond"
	time.Sleep(800 * time.Millisecond) // let the timer expire for SQL_Entity_1

	// Send the third SQL entity to test resetting the timer
	suite.chanDemoSave <- "SQL_Entity_3_300Millisecond"
	time.Sleep(300 * time.Millisecond) // sleep a bit, but not enough for dbSaveWaitDuration

	// Send the fourth SQL entity
	suite.chanDemoSave <- "SQL_Entity_4_800Millisecond"
	time.Sleep(800 * time.Millisecond) // let the timer expire for SQL_Entity_3

	// Send the fourth SQL entity
	suite.chanDemoSave <- "SQL_Entity_5_2500Millisecond"
	time.Sleep(2500 * time.Millisecond) // let the timer expire for SQL_Entity_3

	// Close the channel
	close(suite.chanDemoSave)
}

​

代码动行结果:

Go 复制代码
Received SQL entity: SQL_Entity_1_300Millisecond
Received SQL entity: SQL_Entity_2_800Millisecond
Executing action after delay for entity: SQL_Entity_2_800Millisecond
Received SQL entity: SQL_Entity_3_900Millisecond
Received SQL entity: SQL_Entity_4_800Millisecond
Executing action after delay for entity: SQL_Entity_4_800Millisecond
Received SQL entity: SQL_Entity_5_2500Millisecond
Executing action after delay for entity: SQL_Entity_5_2500Millisecond

从运行结果看,只要超过700ms没有数据进入,就会引发定时器的回调,并且从2500ms的超时看只激发了一次,说明这里的定时器只会运行一次。没有超过700ms的,由于定时器被重置了,又开始等700ms才会运行,运行SQL_Entity_3时,定时器被删除,从结果看,虽然间隔是900ms远超700ms,依然定时器没有执行。接收到SQL_Entity_4时,由于timer已经为nil,因此又重新开启定时器

相关推荐
EF@蛐蛐堂2 分钟前
【js】浏览器滚动条优化组件OverlayScrollbars
开发语言·javascript·ecmascript
代码中介商30 分钟前
C++ 仿函数(Functor)深度解析:从基础到应用
开发语言·c++
小杍随笔1 小时前
Rust桌面GUI框架:性能优化与实战避坑指南
开发语言·性能优化·rust
二哈赛车手1 小时前
新人笔记---项目中简易版的RAG检索后评测指标(@Recall ,Mrr..)实现
java·开发语言·笔记·spring·ai
格林威1 小时前
3D相机视觉检测:环境光太强,结构光点云全是噪点怎么办?
开发语言·人工智能·数码相机·计算机视觉·3d·视觉检测·工业相机
Rust语言中文社区1 小时前
【Rust日报】2026-05-02 Temper - 用 Rust 编写的 Minecraft 服务器项目发布 0.1.0 版
运维·服务器·开发语言·后端·rust
爱滑雪的码农2 小时前
Java基础十一 流(Stream)、文件(File)和IO
java·开发语言·python
叶小鸡2 小时前
Java 篇-项目实战-天机学堂(从0到1)-day11
java·开发语言
格林威2 小时前
线阵工业相机:线阵图像出现“波浪纹”,是机械振动还是编码器问题?
开发语言·人工智能·数码相机·计算机视觉·视觉检测·工业相机·线阵相机