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,因此又重新开启定时器

相关推荐
茉莉玫瑰花茶4 分钟前
C++ 17 详细特性解析(4)
开发语言·c++·算法
福大大架构师每日一题11 分钟前
ollama v0.15.2发布:新增Clawdbot集成指令,全面支持Ollama模型启动!
golang·ollama
rosmis14 分钟前
地铁病害检测系统软件改进记录-2-02
开发语言·前端·javascript
欧阳x天26 分钟前
STL详解(九)—— stack和queue的模拟实现
开发语言·c++
xqqxqxxq27 分钟前
洛谷算法1-1 模拟与高精度(NOIP经典真题解析)java(持续更新)
java·开发语言·算法
沐知全栈开发32 分钟前
Rust 函数
开发语言
zhougl9961 小时前
Java 枚举类(enum)详解
java·开发语言·python
yong99901 小时前
基于势能原理的圆柱齿轮啮合刚度计算MATLAB程序实现
开发语言·matlab
lsx2024061 小时前
R 数组:深入探索与高效使用
开发语言
星火开发设计1 小时前
格式化输入输出:控制输出精度与对齐方式
开发语言·c++·学习·算法·函数·知识